切片Slice
切片本身并不是数组,是指向底层的数组,类似指针。其作为变长数组的替代方案,可以关联底层数组的局部或全部。同时这是一个引用类型,可以直接传教或者从底层数组获取生成。和数组一样,可以使用len()
来获取元素个数,cap()
获取容量。一般使用mark()
进行创建,而不是new ()
。
如果多个slice
指向相同的底层数组,其中一个的值改变会影响到全部
1 | make([]T, len, cap) |
其中cap是可以省略的,默认为与len()
值相同
简单例子
1 | var a []int |
输出
1 | [] |
取元素
取前/后n位元素
1 | func sliceF2() { |
输出
1 | [1 2 4 5 6 7 8 9 10 0] |
包含起始索引,不包含结尾的索引
可以简化下
1 | - s1 := a[5:10] |
往前面取,索引从0~4
1 | s1 := a[:5] |
make
1 | func sliceF3() { |
当元素个数小于等于容量时,不会进行扩容。当大于当前容量时,会分配长度位20且连续的内存块。每次超过时,容量值会翻倍,10->20->40。
容量默认为元素格式
Reslice
Reslice 时索引以被slice的切片为准,索引不可以超过被slice的切片容量cap()
值,索引越界不会导致底层数组的重新分配而是引发错误
1 | func sliceF4() { |
输出
1 | abcdefghijk |
sa 从'c'
的位置开始,一直到a
结束,是一个连续的,所分配的最大容器是 9
Append
在slice尾部追加元素,可以将一个slice追加到另一个slice的尾部,如果最终长度未超过追加到slice的容量则返回原始slice。如果超过,则将会重新分配数组并拷贝原始数据
1 | func sliceF5() { |
输出
1 | 0xc0000d6030 |
超出时,重新分配并拷贝原始数据
1 | func sliceF5() { |
输出
1 | 0xc0000d6030 |
同时指向的影响
多个slice指向同一个底层数组,在操作数组时,会影响到所有关联的slice
1 | func sliceF6() { |
输出
1 | [1 2 3 4] [1 2 3] |
但对slice2进行append操作,并超过其cap()
值时,之后的操作就不会影响到slice2
1 | func sliceF6(){ |
输出
1 | [1 2 3 4] [1 2 3] |
Copy
1 | func sliceF8() { |
输出
1 | [1 2 3] |
s2 中只有3个元素,将会copy前3个元素
只copy s1中的一部分,s1[0:2]
是一个新的slice
1 | + copy(s2, s1[0:2]) |
输出
1 | [1 2 9] |
或者只是替换其中一部分
1 | + copy(s2[1:2], s1[0:2]) |
输出
1 | [7 1 9] |
得到一个完整的数组
1 | s1 := []int{1, 2, 3, 4, 5, 6} |
输出
1 | [1 2 3 4 5 6] |