
copy() 函数不会自动分配目标切片内存,它仅复制 min(len(src), len(dst)) 个元素;若目标切片为空(长度为 0),则无任何元素被复制——必须预先分配足够容量的目标切片。
`copy()` 函数不会自动分配目标切片内存,它仅复制 `min(len(src), len(dst))` 个元素;若目标切片为空(长度为 0),则无任何元素被复制——必须预先分配足够容量的目标切片。
在 Go 中,copy(dst, src) 是标准库提供的内置函数,常被初学者误认为是“创建副本”的万能工具。但实际上,它不负责内存分配,而是一个纯粹的内存拷贝操作:将源切片 src 的前 n 个元素复制到目标切片 dst 的起始位置,其中 n = min(len(src), len(dst))。
这意味着:
✅ 若 dst 已有足够长度(如 make([]int, len(src))),则完整复制成功;
❌ 若 dst 长度为 0(例如 []int{} 或 make([]int, 0)),则 n = 0,复制零个元素,dst 保持不变。
✅ 正确用法:预分配目标切片
arr := []int{1, 2, 3}
tmp := make([]int, len(arr)) // 关键:按需分配长度(非容量!)
copy(tmp, arr)
fmt.Println(tmp) // 输出: [1 2 3]
fmt.Println(arr) // 输出: [1 2 3]? 注意:make([]T, len) 分配的是长度(length),而非仅容量(capacity)。copy() 依赖的是 len(dst),因此必须确保目标切片具有足够长度——容量更大不影响复制,但长度不足会导致截断。
⚠️ 常见错误与误区
- ❌ tmp := []int{} → 长度为 0,copy 无效果;
- ❌ tmp := make([]int, 0) → 同样长度为 0;
- ❌ tmp := make([]int, 0, len(arr)) → 容量充足但长度为 0,仍无法复制;
- ✅ tmp := make([]int, len(arr)) → 长度匹配,安全可靠;
- ✅ tmp := append([]int(nil), arr...) → 利用 append 实现语义化深拷贝(推荐用于简洁场景)。
? 进阶技巧:灵活复制与子切片处理
若只需复制部分元素,可结合切片表达式:
arr := []string{"a", "b", "c", "d", "e"}
partial := make([]string, 2)
copy(partial, arr[1:3]) // 复制 "b", "c"
fmt.Println(partial) // [b c]此外,对于引用类型(如 []*int),copy() 仅复制指针值,不深拷贝底层数据——这是浅拷贝行为,需按需手动处理。
✅ 总结
| 要点 | 说明 |
|---|---|
| 核心规则 | copy(dst, src) 复制 min(len(dst), len(src)) 个元素,长度决定上限 |
| 必要前提 | dst 必须预先通过 make 或字面量初始化,且 len(dst) > 0 |
| 最佳实践 | 使用 make([]T, len(src)) 分配目标切片,清晰、高效、无歧义 |
| 替代方案 | append(make([]T, 0, len(src)), src...) 可避免显式 copy,语义更直观 |
理解 copy() 的“零分配、纯搬运”本质,是写出健壮 Go 切片操作代码的关键一步。










