Go语言切片扩容后元素指针的一致性问题
Go切片扩容后原指针是否会自动指向新地址?
先看你给出的代码示例:
s := make([]int, 0, 10<<20) // 创建一个容量为10M个int元素的切片 s = append(s, 123456789) // 添加一个随机数 p := &s[0] // 指向切片第一个元素的指针 // 添加新元素,切片预期会在内存中重新分配 for i := 0; i < 100<<20; i++ { s = append(s, i) }
直接给结论:指针p不会自动指向切片s第一个元素的新地址,必须重新创建指针(也就是重新执行p = &s[0])才能拿到新地址。
原因很简单:Go里的切片本质是个包含三个字段的结构体——指向底层数组的指针、切片长度、切片容量。当append触发扩容时,Go会分配一块新的更大的内存空间,把原底层数组的内容拷贝过去,然后更新切片结构体里的指针指向这块新内存。但你之前创建的p是独立的指针变量,它存的是旧底层数组第一个元素的地址,不会因为切片内部指针的变化而自动更新。
哪怕原切片里的123456789已经被拷贝到新底层数组的第一个位置,p指向的还是旧内存里的那个值,和新切片的第一个元素已经不是同一个地址了。如果之后需要指向新切片的第一个元素,必须重新获取地址。
内容的提问来源于stack exchange,提问作者Dmitry
相关产品推荐
相关产品推荐

