Go语言切片append操作异常:为何输出结果为[4,5,3]?
问题原因解析
这本质是Go语言slice的底层数组共享特性导致的,核心逻辑如下:
先还原典型场景代码
假设你的代码逻辑类似这样:
type QueueStruct struct { Queue []int } func main() { // 创建容量5、长度0的slice rawSlice := make([]int, 0, 5) // 赋值给结构体字段 q := QueueStruct{Queue: rawSlice} // 给结构体的Queue字段追加1、2 q.Queue = append(q.Queue, 1, 2) // 给原slice追加4、5 rawSlice = append(rawSlice, 4, 5) // 再给结构体的Queue字段追加3 q.Queue = append(q.Queue, 3) // 实际输出:[4,5,3] fmt.Println(q.Queue) }
一步步拆解为什么会出现[4,5,3]
- slice的本质:Go的slice是包含三个字段的结构体:
指向底层数组的指针、当前长度(len)、当前容量(cap)。当你把slice赋值给结构体字段时,只是复制了这个slice结构体,两个slice会共享同一个底层数组,但各自的len、cap是独立的。 - 第一次追加(结构体字段):
q.Queue初始len=0、cap=5,追加1、2后,len变为2,底层数组的第0、1位被写入1、2,此时底层数组是[1,2,0,0,0]。 - 第二次追加(原slice):
rawSlice的len还是0、cap=5,追加4、5会从底层数组的第0位开始写入,直接把原来的1、2覆盖成4、5,底层数组变成[4,5,0,0,0]。 - 第三次追加(结构体字段):
q.Queue的len仍然是2,追加3会从底层数组的第2位写入,把0改成3,此时底层数组是[4,5,3,0,0],而q.Queue的len是3,所以输出时只取前3位,就是[4,5,3]。
为什么容量改为0就符合预期?
当你创建rawSlice := make([]int, 0, 0)时,第一次给q.Queue追加1、2时,因为cap=0没有多余空间,Go会重新分配一个新的底层数组给q.Queue。此时rawSlice和q.Queue的底层数组不再共享,后续各自的追加操作只会修改自己的底层数组,结果自然符合你的预期。
内容的提问来源于stack exchange,提问作者Ray Kim
相关产品推荐
相关产品推荐

