截取创建共享底层数组的视图,零开销但修改相互影响;copy() 逐元素复制生成独立副本,o(n) 开销但保障数据隔离。关键判断:是否允许修改一方影响另一方——不允许则必须用 copy()。

copy() 和切片截取(如 s[a:b])根本不是同一类操作
它们解决的问题完全不同:copy() 复制值,产生独立数据;截取只是创建新视图,共享底层数组。性能对比本身容易误导——就像比“搬家具”和“换个窗户看同个房间”谁更快。你真正该问的是:此刻需要独立副本,还是仅需临时视图?
截取操作几乎零开销,但修改会相互影响
执行 s2 := s1[2:5] 只是复制三个机器字(指针、len、cap),耗时恒定且极小。但它不分配新内存,s2 和 s1 指向同一底层数组片段。
- 修改
s2[0]会直接改到s1[2] - 后续对
s1调用append可能触发扩容,导致s2的底层数组被替换——此时s2不再反映s1的变化,但也不会 panic - 若原切片已很大,而你只截取几个元素,却长期持有该子切片,会阻止整个底层数组被 GC 回收
copy() 有明确内存和时间成本,但换来数据隔离
copy(dst, src) 是按元素逐个拷贝(底层调用 memmove),时间复杂度 O(n),且要求 dst 已预分配空间。它的开销真实存在,但换来的是关键保障:修改 dst 绝不影响 src,反之亦然。
- 目标切片
dst必须用make([]T, len(src))或类似方式预先分配,否则copy()返回 0,什么也不做 - 若
len(src) > len(dst),只复制前len(dst)个元素,不 panic - 若
dst容量很小,后续append(dst, x)可能触发新底层数组分配,但这是预期行为,与原始src完全无关
什么时候该选 copy(),而不是截取
核心判断就一条:是否允许后续修改一方影响另一方。只要答案是“不允许”,就必须用 copy(),别省那点 CPU 时间。
- 函数返回“当前快照”,但内部还要继续追加数据 → 返回前
copy()出新切片 - 从网络读取一批数据进缓存切片,同时启动 goroutine 异步处理 → 处理前必须
copy(),否则后续读取会覆盖正在处理的数据 - 实现类似
Clone()方法,对外暴露不可变视图 → 内部用copy()构建新底层数组 - 只是遍历、只读、生命周期短 → 直接截取,更轻量
最容易被忽略的点:截取后你以为自己拿了个“小切片”,其实锁住了整个大底层数组;而 copy() 看似多花了点时间,却让 GC 能及时回收旧内存——这对长周期服务尤其关键。











