Golang中的slice本质是什么?为何sliceHeader被普遍认为是关键,而slice.go里的定义又是什么?

Golang中的slice本质是什么?为何sliceHeader被普遍认为是关键,而slice.go里的定义又是什么? 所以?

6 回复

是的,sliceHeader 的作用不太明确。 我的英语不是很好,我使用了谷歌翻译。

更多关于Golang中的slice本质是什么?为何sliceHeader被普遍认为是关键,而slice.go里的定义又是什么?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这里没有提到与 sliceHeader 相关的内容。

“本质”是抽象且隐喻的概念。您具体指的是什么?您是对切片对象在运行时的表现形式感兴趣吗?

你是否阅读过:Go Slices: usage and internals - go.dev(这里有一个通过谷歌翻译翻译成中文的链接)。

“切片内部结构”中文)部分描述了切片的工作原理。在示例中,有三个字段:ptrlencap。这些字段分别对应 slice 结构体的 arraylencap 字段。

在Golang中,slice的本质是一个三元数据结构,包含指向底层数组的指针、长度和容量。sliceHeader是理解slice内部实现的关键,因为它揭示了slice在内存中的实际布局。

slice.go中的定义如下:

type slice struct {
    array unsafe.Pointer
    len   int
    cap   int
}

示例代码展示sliceHeader的使用:

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    // 创建slice
    s := make([]int, 5, 10)
    s[0] = 1
    s[1] = 2
    
    // 通过unsafe.Pointer访问sliceHeader
    header := (*[3]int)(unsafe.Pointer(&s))
    
    fmt.Printf("指针地址: %p\n", unsafe.Pointer(header[0]))
    fmt.Printf("长度: %d\n", header[1])
    fmt.Printf("容量: %d\n", header[2])
    
    // 验证slice操作
    s = append(s, 3, 4, 5)
    fmt.Printf("追加后长度: %d, 容量: %d\n", len(s), cap(s))
}

sliceHeader之所以关键,是因为它解释了slice的共享底层数组特性:

package main

import "fmt"

func main() {
    arr := [5]int{1, 2, 3, 4, 5}
    s1 := arr[1:4]  // 指向arr[1]到arr[3]
    s2 := s1[0:2]   // 与s1共享底层数组
    
    s2[0] = 99
    fmt.Println(arr)  // [1 99 3 4 5]
    fmt.Println(s1)   // [99 3 4]
    fmt.Println(s2)   // [99 3]
}

slice.go中的定义是runtime包中的内部实现,虽然与reflect包中的SliceHeader结构相似,但直接使用unsafe.Pointer访问slice内部结构是更准确的方式。

回到顶部