为什么Go中slice执行append操作后未更新对应的引用切片?
问题原因
你遇到的现象核心原因是给fruits执行append时已经触发了扩容,此时fruits和newFruits不再共享底层数组,后续修改newFruits自然不会影响fruits的取值,我们可以逐行拆解执行逻辑验证:
- 初始化
var fruits = []string{"banana", "mango", "tomato"}时,fruits的长度(len)为3,容量(cap)为3,指向底层数组A。 - 执行
var newFruits = fruits[1:2]时,newFruits基于数组A生成,长度为1,容量为原cap - 起始索引 = 3 - 1 = 2,此时两个切片确实共享数组A。 - 执行
fruits = append(fruits, "papaya")时,fruits当前len等于cap,没有多余空间存储新元素,触发扩容规则:Go会申请容量翻倍的新底层数组B(字符串切片容量小于1024时默认翻倍,所以新cap为6),把数组A的所有元素拷贝到B,再追加新元素"papaya",最后把fruits的内部指针指向数组B。这一步完成后,fruits和newFruits已经完全没有共享内存了。 - 执行
newFruits = append(newFruits, "dragon")时,newFruits的len=1<cap=2,有多余空间,所以直接在旧数组A的空余位置写入"dragon",这个修改只会作用在数组A上,和fruits指向的数组B没有任何关联,自然不会修改fruits的取值。
另外你代码里的注释写反了,实际运行时:
cap(fruits)输出为6cap(newFruits)输出为2
刚好符合上面的推导逻辑。
内容的提问来源于stack exchange,提问作者nowodev
相关产品推荐
相关产品推荐

