
copy() 函数仅复制 min(len(src), len(dst)) 个元素,因此目标切片必须预先分配足够容量,否则复制失败(如空切片 []int{} 的长度为 0,导致无任何元素被复制)。
`copy()` 函数仅复制 `min(len(src), len(dst))` 个元素,因此目标切片必须预先分配足够容量,否则复制失败(如空切片 `[]int{}` 的长度为 0,导致无任何元素被复制)。
在 Go 中,copy() 是一个内置函数,常被开发者误认为是“创建副本”的快捷方式。但它的实际行为是内存级别的元素搬运,而非自动扩容或初始化目标切片。其核心规则非常明确:复制元素数量 = min(len(src), len(dst))。这意味着:若目标切片 dst 长度为 0(例如 []int{} 或 make([]int, 0)),无论源切片多长,复制结果都为 0 个元素——这正是初学者遇到 tmp 始终为空的根本原因。
✅ 正确用法:预分配目标切片
要可靠地复制一个切片,必须确保目标切片具有至少与源切片相等的长度(length)。最常用且推荐的方式是使用 make() 显式创建:
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, n) 创建长度和容量均为 n 的切片;若需后续追加,可改用 make([]T, 0, n)(零长度、足量容量),再配合 append() 使用。
⚠️ 常见错误与陷阱
-
错误 1:使用未初始化或零长度切片
tmp := []int{} // len=0 → copy() 不复制任何元素 tmp := make([]int, 0) // 同样 len=0 → 复制失效 错误 2:忽略容量(capacity)与长度(length)区别
copy() 只关心 len(dst),不检查 cap(dst)。即使容量充足但长度不足(如 make([]int, 1, 10)),也最多复制 1 个元素。错误 3:混淆 copy() 与深拷贝语义
copy() 仅进行浅层复制:对于 []*int 或 []struct{} 等含指针/结构体的切片,它复制的是指针值或结构体副本,不会递归克隆底层数据。需深拷贝时应使用 encoding/gob、json 序列化,或手动实现。
? 补充:安全复制的封装建议
为提升代码健壮性,可封装一个通用复制函数:
func CloneSlice[T any](src []T) []T {
if src == nil {
return nil
}
dst := make([]T, len(src))
copy(dst, src)
return dst
}
// 使用示例
original := []string{"a", "b", "c"}
duplicate := CloneSlice(original) // 安全、清晰、泛型支持✅ 总结
copy() 不是“复制切片”的魔法函数,而是一个低开销、高可控的内存拷贝工具。它的行为完全由源与目标切片的 长度 决定。牢记三步法则即可避免绝大多数问题:
- 检查源切片是否非 nil;
- 为目标切片显式分配长度 ≥ len(src);
- 调用 copy(dst, src) 并可选校验返回值(应等于 len(src))。
遵循此模式,你就能在性能敏感场景中高效、安全地完成切片复制。










