因为 append 可能触发底层数组扩容,此时旧切片的 data 指针已失效,原变量仍指向旧内存——不返回就无法拿到新地址。
切片本质是三元组:ptr(指向底层数组)、len、cap。扩容时系统 malloc 新数组、复制数据、更新 ptr,但调用者传入的只是值拷贝,函数内修改不影响外部变量。
append 超出旧 cap)
扩容触发条件只看 len 和 cap:当 len + 1 > cap 时必须分配新底层数组。
具体策略由运行时决定:小切片通常翻倍,大切片按 1.25 倍增长,但这是实现细节,不可依赖。
make([]int, 0, 4) 再 append 第 5 个元素 → 必扩容nil 切片首次 append → 总是分配新数组(哪怕只加 1 个元素)[:] 截取而来,cap 可能远大于 len,此时多次 append 也不扩容
最常见的是循环中反复 append 却不更新变量,导致只有最后一次写入生效,或 panic。
|
|
另一个隐蔽问题:在函数参数中传入切片并试图原地修改
|
|
index out of range 或静默丢数据&s[0] 会发现地址突变,但没人检查这个go vet 能捕获部分未使用返回值的情况,但非全部唯一原则:永远用返回值覆盖原变量,除非你明确知道当前操作不会扩容且不需要结果。
s = append(s, x) 或 s = append(s, x, y, z)s = append(s, t...)(注意 ... 不可省略)s := make([]int, 0, 100)len(s) 且只追加 1 个元素,但仍建议显式赋值底层数组是否变更不是你能控制的,是运行时根据当前状态做的决策。依赖“没扩容”来跳过赋值,等于把逻辑建立在沙滩上。
版权声明: 本站资源均来自互联网或会员发布,如果侵犯了您的权益请与我们联系,我们将在24小时内删除!谢谢!联系QQ:76900276