s1 := []int{1, 2, 3, 4}
s2 := []int{-1, -2, -3}
fmt.Println(append(s1[:1], s2...))
fmt.Println(s1)
打印的结果:
[1 -1 -2 -3]
[1 -1 -2 -3]
弄不明白的是:为什么s1的值也变了?
s1 := []int{1, 2, 3, 4}
s2 := []int{-1, -2, -3}
fmt.Println(append(s1[:1], s2...))
fmt.Println(s1)
打印的结果:
[1 -1 -2 -3]
[1 -1 -2 -3]
弄不明白的是:为什么s1的值也变了?
7 回答5.3k 阅读
6 回答6.9k 阅读✓ 已解决
4 回答2.3k 阅读
1 回答3.4k 阅读
2 回答879 阅读✓ 已解决
2 回答2.2k 阅读
1 回答2.1k 阅读
因为append函数并不保障slice是否被修改,也就是说append可能会修改slice,也可能不修改,所以使用append有两个原则:
append函数调用后,应该使用返回值作为结果。
append函数调用后,不应该再使用实参传入的slice。
所以使用append函数一般都是
s = append(s,elem1)
这种用法,也就是把结果重新赋值给原来的slice。append函数之所以有这个表现,是因为slice的底层存储依赖于底层数组(underlying array),用你的例子来给你说明一下:
你的s1初始化的值是
[]int{1, 2, 3, 4}
,它的len和cap都是4,所以它的底层数组是一个长度为4的数组[4]int{1,2,3,4}
。基于slice的特点,
s1[:1]
和s1是共享底层数组的,所以s1[:1]
这个slice的改变是会影响到underlying array的。append函数在填充elem1,elem2的时候会先判断slice的cap是否能容纳所有追加的值,这个计算方式是从slice的尾部计算的,在你的例子里,slice的尾部是第一个元素,后面的容量恰好可以满足3个元素,所以它不会申请新的底层数组,而会直接使用原有的底层数组作为存储,这也就把原本的底层数组改成了[1 -1 -2 -3],由于s1的存储依赖于这个底层数组,自然也就变成了
[1 -1 -2 -3]
。如果把你的例子改成
append(s1[:1],1, s2...)
,或者改成append(s1[1:2], s2...)
,你就会发现s1没有被改变,这是因为容量不能容纳所有追加元素,append会申请一个新的底层数组用来存储,也会返回一个新的slice,这不会影响到原本的底层数组,也就不会影响到原本的slice。所以使用
s = append(s,elem1)
是一个好习惯,尽量使用这个用法。