You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言切片append操作疑惑:为何修改y有时会影响x?

Go切片append操作的底层逻辑解析

要搞懂这几个示例的差异,核心得先明白Go切片的本质:每个切片都绑定了一个底层数组,切片自身只存三个值:当前长度(len)、最大容量(cap)、指向底层数组的指针。append操作的行为完全取决于「新增元素后是否超过切片容量」:

第一个示例:未触发扩容,共享底层数组

先看代码:

x := make([]int, 0, 4)
x = append(x, 1, 2, 3, 4) // len(x)=4,cap(x)=4
y := x[:2]                // len(y)=2,cap(y)=4(切片容量从起始索引到底层数组末尾)

y = append(y, 30, 40)

fmt.Println("x:", x) // 输出 [1 2 30 40]
fmt.Println("y:", y) // 输出 [1 2 30 40]
  • y的初始len是2,append两个元素后,len变成4,刚好等于它的cap(4),不需要扩容。
  • 这时候append直接在共享的底层数组上修改:把数组索引2、3位置的原有值(3、4)替换成30、40。
  • x的len是4,刚好覆盖整个底层数组,所以x输出的就是修改后的数组内容。

第二个示例:触发扩容,生成新底层数组

代码:

x := make([]int, 0, 4)
x = append(x, 1, 2, 3, 4) // len(x)=4,cap(x)=4
y := x[:2]                // len(y)=2,cap(y)=4

y = append(y, 30, 40,50)

fmt.Println("x:", x) // 输出 [1 2 3 4]
fmt.Println("y:", y) // 输出 [1 2 30 40 50]
  • y初始len是2,append三个元素后,len变成5,超过了cap(4),触发自动扩容。
  • Go会分配一个新的底层数组(容量通常是原容量的2倍,这里原cap是4,新容量一般为8),把y原有的元素(1、2)和新增元素(30、40、50)复制到新数组里。
  • 此时y指向新数组,而x仍然指向原来的旧数组,所以x的内容不受影响,还是原来的[1,2,3,4]。

第三个示例:容量足够但原切片长度未覆盖修改位置

代码:

x := make([]int, 0, 5)
x = append(x, 1, 2, 3, 4) // len(x)=4,cap(x)=5
y := x[:2]                // len(y)=2,cap(y)=5

y = append(y, 30, 40, 50)

fmt.Println("x:", x) // 输出 [1 2 30 40]
fmt.Println("y:", y) // 输出 [1 2 30 40 50]
  • y的cap是5,append三个元素后len变成5,刚好等于cap,不需要扩容,直接在共享底层数组上修改:索引2、3、4位置分别写入30、40、50。
  • x的len是4,它只「看得见」底层数组的前4个元素(索引0-3),索引4的50不在x的长度范围内,所以x输出时不会显示这个值;而y的len是5,覆盖了整个数组,所以能看到全部5个元素。

内容的提问来源于stack exchange,提问作者greedsin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 06:54:35