slice切片-golang复习
复习一下切片,slice
例子
demo1
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7} //数组
s := arr[2:6] //从数组取2—6
fmt.Println(s) //输出 [2 3 4 5]
fmt.Println(arr[:6]) // [0 1 2 3 4 5] 省略头直接从0开始
fmt.Println(arr[2:]) // [2 3 4 5 6 7] 省略尾巴直接到末尾
fmt.Println(arr[:]) // [0 1 2 3 4 5 6 7] 头尾都省了全部都有
}
demo2
slice不是一个值类型,是数据结构视图
arr[:6]
是对于 arr
的一个视图
[]int
表示一个slice 没有...或者长度,与数组区别
func updateSlice(s []int) {
s[0] = 100
}
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
s1 := arr[2:] //[2 3 4 5 6 7]
fmt.Println(s1) // 修改前 [2 3 4 5 6 7]
updateSlice(s1) //执行修改
fmt.Println(s1) //[100 3 4 5 6 7] //切片0的位置改为了100
fmt.Println(arr) //[0 1 100 3 4 5 6 7] 原来数组的相应位置2 也被改成了100
}
因为s1作为arr的一个切片,算是一个视图,所以s1改动时候影响到arr数组的相应位置也发生改动
貌似用来修改数组是个好方案,省得用指针改
总结:slice本身没有数据,slice是对底层array的一个视图
demo3
reslice 在slice上面建立slice
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
s2 := arr[:] //取得arr全部
fmt.Println(s2) //[0 1 2 3 4 5 6 7]
s2 = s2[:5] //在s2上面取开始到5
fmt.Println(s2) //[0 1 2 3 4]
s2 = s2[2:] //在去过开始到5基础上的s2 上面再取2到结束
fmt.Println(s2) //[2 3 4]
}
可以在一个底层array上面建立多个slice
可以在slice基础上再建立slice,但是底层还是同一个array
demo3
extending slice 拓展slice
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
s1 := arr[2:6]
fmt.Println(s1) //[2 3 4 5]
s2 := s1[3:5] //在s1基础上取 3,4 但是实际上最后就只有第3位指向的5,而没有4指向的(直接打印s1[4]都会报错
fmt.Println(s2) //[5 6] //结果取到了5 6,⚠️但是6压根不在s1里面
}
s2在s1上面取,然后取到了并不在s1中的数据,超出的数据实际上是底层arr的数据——切片的推展
slice下面有 ptr
len
cap
只要不超过 cap就可以拓展 cap是底层的array slice可以向后扩展,不可以向前扩展
s[i] 不可以超过
len(s),向后扩展不可以超过底层数组
cap(s)`
demo4
len和cap
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
s1 := arr[2:6]
fmt.Printf("%v,%d,%d", s1, len(s1), cap(s1)) //[2 3 4 5],4,6 len就是4,cap就是6(还可以往后拓展到 [6 7]
}
len就是当前视图slice切片容量,cap就是向后可以拓展到底层array数组的容量
demo5
向slice append操作
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
s2 := arr[5:7] //[5 6]
s3 := append(s2, 10) //[5 6 10]
s4 := append(s3, 11) //[5 6 10 11]
s5 := append(s4, 12) // [5 6 10 11 12]
fmt.Println("s3,s4,s5=", s3, s4, s5) //s3,s4,s5= [5 6 10] [5 6 10 11] [5 6 10 11 12]
fmt.Println("arr=", arr) //arr= [0 1 2 3 4 5 6 10] //即使上面加到了12,但是最多对原来的底层arr影响也在10,没有超过容量
}
即使上面slice数据加到了12,但是最多对原来的底层arr影响也在10,没有超过arr容量。而11,12这些实际上进入到了一个新开的array里面(容量比原来的要大)——> s4,s5的slice已经不再是arr为底层array,由系统分配了一个新的array作为底层
添加元素时超过cap,系统会重新分配更大的底层数组,并且复制原来的值
原来的arr数组如果有用会被留下,没有用会被垃圾回收机制回收掉
由于值传递的关系,必须接收append的返回值
也就是类似 s = append(s,val)
demo6
demo6-1
创建slice 空的nil的 slice
func printSlice(s []int) {
fmt.Printf("len=%d,cap=%d\n", len(s), cap(s))
}
func main() {
var s []int
for i := 0; i < 5; i++ {
printSlice(s)
s = append(s, 2*i+1)
}
fmt.Println(s)
}
输出
len=0,cap=0
len=1,cap=1
len=2,cap=2
len=3,cap=4
len=4,cap=4
[1 3 5 7 9]
demo6-2
:= []int
创建
func main() {
s1 := []int{2, 4, 6, 8}
printSlice_c(s1) //len=4,cap=4
}
demo6-3
make
知道slice容量,但是不知道里面的值
func main() {
s1 := make([]int, 16)
s2 := make([]int, 10, 32)
printSlice_d(s1) //len=16,cap=16
printSlice_d(s2) //len=10,cap=32
}
demo7
复制copy slice
func main() {
s1 := []int{1, 2, 3, 4} //[1 2 3 4]
s2 := make([]int, 8) //[0 0 0 0 0 0 0 0]
copy(s2, s1) //把s1的值复制到s2
fmt.Println(s2) //[1 2 3 4 0 0 0 0]
}
copy(复制到的位置,用于复制的数据)
###demo8
删除中间slice的值
func main() {
s1 := []int{1, 2, 3, 4, 5, 0, 0, 0}
fmt.Println(s1) //[1 2 3 4 5 0 0 0]
s1 = append(s1[:3], s1[4:]...) //删除了4
fmt.Println(s1) //[1 2 3 5 0 0 0]
}
由于没有给删除值的函数,所以用append
来处理
s1[4:]...
中的...
表示把4以后的值全部往前面挪
删除首尾slice的值
func main() {
s1 := []int{1, 2, 3, 4, 5, 0, 0, 0}
fmt.Println(s1) //[1 2 3 4 5 0 0 0]
//删除头
front := s1[0] //1
s1 = s1[1:]
//删除尾
tail := s1[len(s1)-1] //0
s1 = s1[:len(s1)-1]
fmt.Println(front, tail) //1 0
fmt.Println(s1) //[2 3 4 5 0 0]
}
删除头就把 [1:]
的值赋给原来的slice
删除尾就把 [:len(s)-1]
的值赋给原来的slice
删除会改变 len
,不会改变 cap