切片-slice
1.其本身并不是数组,它指向底层的数组,作为变长数组的替代方案,可以关联底层数组的局部和全部为引用类型;
2.可以直接创建或从底层数组获取生成;
3.使用len() 获取元素个数,使用cap()获取容量;
4.一般使用make创建
5.如果多个slice指向相同底层数组,其中一个值改变会影响全部;
6.make([]T,len,cap),其中cap可以省略,则和len的值相同;
一、创建slice
1.声明一个空的slice
var s1 []int
输出 :[] 长度为0
2.从数组中获取slice
a := [10]int{} //长度为10的int数组
s1 := a[9] //取索引为9的元素
s1 := a[5:10] // 取索引为5,6,7,8,9的元素;:号之前为起始位置,之后为截至位置,包头不包尾;
s1 := a[5:len(a)]
或
s1 := a[5:] // 取索引为5和之后的元素;
s1 := a[:5]
或
s1 := a[0:5] // 取索引为5之前(不包含索引5)的元素;
3.make函数声明slice (比较正式)
s1 := make([]int,3,10) //make([]T,len,cap)cap初始容量,超过数组容量的分配长度,会以一倍的方式增容;
即:当s1的长度超过10小于20时cap扩容为20;
二、Reslice
- Reslice时索引以被Slice的切片为准;
2.索引不可以超过被slice的切片的容量cap()值
3.索引越界不会导致底层数组的重新分配而是引发错误;
三、Append函数
1.可以在slice尾部追加元素;
2.可以将一个slice追加到另一个slice尾部;
3.如果最终长度未超过追加到slice的容量则返回原始slice;
4.如果超过追加到的slice的容量则重新分配数组并拷贝原始数据;
s1 := make([]int, 3, 6) //元素个数为3,容量为6的slice
fmt.Printf("%p\n", s1)
s1 = append(s1, 1, 2, 3) //追加3个元素
fmt.Printf("%v %p\n", s1, s1)
//追加之后s1的容量为6,未超出原始容量,地址不变;
fmt.Println(a)*/
s2 := make([]int, 3, 6) //元素个数为3,容量为6的slice
fmt.Printf("%p\n", s2)
s2 = append(s1, 1, 2, 3,4,5) //追加3个元素
fmt.Printf("%v %p\n", s2, s2)
//追加之后s1的容量为8,超出原始容量,重新分配内存地址,拷贝原始数据,然后再追加;
四、Copy函数
s1 := []int{1, 2, 3, 4, 5, 6,7}
s2 := []int{8, 9, 10}
copy(s1, s2) //将s2copy到s1
fmt.Println(s1) //[ 8 9 10 4 5 6 7]
copy(s2, s1) //将s2copy到s1
fmt.Println(s2) //[1 2 3]
s1 := []int{1, 2, 3, 4, 5, 6, 7}
s2 := []int{8, 9, 10, 1, 1, 1, 1}
copy(s2[2:4], s1[1:3]) //将s1中索引为1到3的元素copy到s2中索引为2到4的位置,s2如果不指定位置则默认从0开始
fmt.Println(s2) //[8 9 2 3 1 1 1]