Dig101: dig more, simplified more and know more
Slice作为go常用的数据类型,在日常编码中非常常见。
相对于数组的定长不可变,slice使用起来就灵活了许多。
0x01 slice 到底是什么?
首先我们看下源码中slice结构的定义
1 2 3 4 5 6
| type slice struct { array unsafe.Pointer len int cap int }
|
slice数据结构如上,Data指向底层引用的数组内存地址, len是已用长度,cap是总容量。
为验证如上所述,我们尝试声明一个slice a,获取 a的sliceHeader头信息,并用%p
获取&a, sh, a, a[0]
的地址
看看他们的地址是否相同。
1 2 3 4 5 6 7 8
| a := make([]int, 1, 3)
sh := (*reflect.SliceHeader)(unsafe.Pointer(&a)) fmt.Printf("slice header: %#v\naddress of a: %p &a[0]: %p | &a: %p sh:%p ", sh, a, &a[0],&a, sh)
|
结果发现a和&a[0]
地址相同。 这个好理解,切片指向地址即对应底层引用数组首个元素地址
而&a和sh及sh.Data
指向地址相同。这个是因为这三个地址是指slice自身地址。
这里【slice自身地址不同于slice指向的底层数据结构地址】, 清楚这一点对于后边的一些问题会更容易判断。
Read More