切片底层数组在未超出原容量时被复用;append 超出 cap 会扩容并复制,导致原引用失效;判断依据是 len(s)+n ≤ cap(s)。
切片底层数组何时被复用?
Go 的切片是引用类型,底层共享同一段数组内存。只要没超出原数组容量,新切片就复用底层数组——这是高效的关键,也是隐患的源头。
常见错误现象:append 后原切片内容被意外修改,或函数返回的切片在调用方继续 append 时触发扩容,导致底层数组复制,旧引用失效。
- 判断是否复用:检查
cap(s)是否足够容纳新增元素;若len(s) + n ,则复用;否则分配新底层数组 - 避免意外共享:需隔离数据时,显式拷贝,如
newSlice := append([]T(nil), oldSlice...)或copy(dst, src) - 注意
make([]T, len, cap)中cap设得过大,虽避免频繁扩容,但会占用更多未使用的内存
预估容量能省多少次内存分配?
每次 append 超出 cap 时,运行时按近似 2 倍策略扩容(小 slice 可能是 +1、+2、×2),反复分配、拷贝、释放带来 GC 压力和延迟抖动。
使用场景:批量构建切片(如解析 JSON 数组、读取文件行、聚合 DB 查询结果)。