slice的底层是数组,是对数组的view
Go语言中的变量类型大多都是值类型,而slice是引用类型。官方文档中描述slice是对数组的一种view(视图)
下面我门看slice的一个特殊例子:
arr := […]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
s1 := arr[2:6]
s2 := s1[3:5]
那么问题来了,s1可以很容易的得出答案是2,3,4,5
但是s2呢?s2能不能取到值?
答案是可以的,s2的值是5,6
,但是6并不在s1当中,这就涉及到slice对底层数组的view机制了。
s1在view底层数组的时候,把从下标2开始的对应的值view到了自己对应的下标。具体过程如图:

slice的底层实现
slice中有三个属性:
ptr
:指向slice的开头位置
len
:代表了slice的长度,当下标>=len
的时候就会提示越界
cap
:代表了从ptr
到结束的整个的长度,在扩展的时候只要不超过cap
就可以扩展

所以说,slice看不见ptr之前的元素,并且slice只能向后扩展,扩展可以超过len(s)但是不能超过cap(s)
操作slice
向slice添加元素
那么问题又来了,我们来看下面的例子:
arr := […]int{0, 1, 2, 3, 4, 5, 6, 7}
s1 := arr[2:6]
s2 := s1[3:5]
s3 := append(s2, 10)
s4 := append(s3, 11)
s5 := append(s4, 12)
这时,s3,s4,s5的值是多少?arr的值又是多少?
答案如图:

这里可以看到arr的长度并没有变,仅仅是因为append 10的影响,把7变成了10,那之后的11,12去了哪里?
这时,s3,s4 view 的并不是原来的arr了,因为超过了原来的arr的长度,系统会新建一个更长的arr把元素拷贝过去,s3,s4 view 的就是更大的底层数组。
总的来说:
添加元素时如果超越了cap,系统就会重新分配更大的底层数组
由于值传递的关系,必须接收append的返回值s = append(s,v)
创建slice
s1 := []int{2, 4, 6, 8}
s2 := make([]int, 16) // make 告知len长度
s3 := make([]int, 16, 32) // make 告知len和cap长度
复制slice
copy(s2, s1)
删除slice中的元素
s1 = append(s1[:3], s1[4:]…)