切片本身一个结构体,由指针、len和cap组成 切片的 地址跟数组首元素的地址是两码事
type slice struct {
array unsafe.Pointer
len int
cap int
}
切片的地址跟数组的首元素的地址是两码事 ,当&slice的时候,取到的是属性array的地址,
//数组地址
arrays := [2]int{}
fmt.Println(unsafe.Pointer(&arrays))
fmt.Println(&arrays[0])
//切片地址
ints := make([]int, 2)
fmt.Println(unsafe.Pointer(&ints))
fmt.Println(&ints[0])
切片初始化
var s []int
s = []int{} //初始化,len=cap=3
s = make([]int, 3) //初始化,len=cap=3
s = make([]int, 3, 5) //初始化,len3,cap=5
s = []int{1, 2, 3, 4, 5} //初始化,len=cap=5
s2d := [][]int{
{1}, {2, 3}, //二维数组各行的列数相等,但二维切片各行的len可以不等
}
append
- 切片相对于数组最大的特点就是可以追加元素
- 追加的元素放到预留的内存空间里,同时len+1
- 如果预留空间已用完,则会重新申请一块更大的内存空间 capacity变成之前的2倍(cap<1024)或1.25倍(1024<cap)。把原内存空间的数据拷贝过来,在新内存空间上执行append操作。
截取子切片
- s:=make([]int,3,5)//le=3,cap=5
- sub_slice=s[1:3] //len=2,cap=4
- 刚开始,子切片和母切片共享底层的内存空间,修改子切片会反映到母切片上,在子切片上执行append会把新元素放在母切片上的预留内存空间上。
- 当子切片不断执行append,消耗完了母切片预留内存空间,子切片跟母切片就会发生内存分离,此后两个切片没有任何关系。