最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
在Go语言中通过语言学习理解深拷贝与浅拷贝的差异
时间:2026-07-20 17:25:54 编辑:袖梨 来源:一聚教程网
Go语言无深拷贝特性,赋值均为值传递;struct浅拷贝逐字段复制:值类型完全独立,引用类型共享底层数据;slice需make+copy实现真隔离;反射或序列化深拷贝有局限,手动按语义逐字段处理最可靠。
Go 语言里没有“深拷贝”这个语言特性,所有赋值、传参、返回都是值传递;所谓深/浅,只取决于你操作的是什么类型、它底层是否含引用字段。
struct 赋值默认是浅拷贝,但不是所有字段都共享
写 copy := original 时,Go 会逐字段复制:
- 值类型字段(
int、string、不含指针的嵌套struct):内存内容完整复制,改copy.Age不影响original.Age - 引用类型字段(
[]T、map[K]V、*T、chan T):只复制头信息(如 slice 的len/cap/底层数组指针),底层数据仍共用
例如 original.Tags 和 copy.Tags 指向同一底层数组,改 copy.Tags[0] 就等于改 original.Tags[0];original.Info 和 copy.Info 若为 *Detail,则两者解引用后操作的是同一块内存。
slice 拷贝必须用 copy() 才算值拷贝
b := a 或 b := a[:] 都是浅拷贝——两个 slice 共享底层数组。要真正隔离,得手动分配新底层数组:
立即学习“go语言免费学习笔记(深入)”;
- 先
make([]T, len(a))分配空间 - 再
copy(b, a)复制元素值 - 若
T本身含引用字段(如[]map[string]int),copy()只复制外层 slice,内部 map 仍共享,需额外递归处理
不这么做,哪怕只改 b[0].Name,a[0].Name 也会变。
用反射或序列化实现深拷贝时,要注意语义丢失
第三方库如 deepcopy 或手写反射递归,能自动处理嵌套 map、slice、struct,但有硬伤:
- 未导出字段(小写开头)无法被反射访问,直接跳过
-
func、chan、unsafe.Pointer无法安全复制,通常 panic 或忽略 - JSON 序列化方案(
json.Marshal+json.Unmarshal)会丢掉方法、空接口类型、循环引用,且要求字段可导出
这些不是“实现不到位”,而是 Go 类型系统本身不支持通用深拷贝——你得自己决定哪些字段该深、哪些该共享、哪些该忽略。
手动深拷贝的关键是明确字段意图
比起依赖通用方案,更可靠的是按业务语义逐字段写拷贝逻辑:
-
[]T:用make+copy,若T是结构体且含指针,对每个T再调用其自有拷贝方法 -
map[K]V:make(map[K]V)后遍历赋值,若V是引用类型,也需递归深拷贝 -
*T:判空后dst = &(*src),若T有引用字段,继续展开
最易被忽略的点是:深拷贝不是技术问题,而是设计问题——你要拷什么、不拷什么、怎么处理 nil、如何应对自引用,这些都没法靠一个函数自动推断。
相关文章
- 《龙之谷》十六周年:光明浪客新职业亮相 融合传统武术仙侠特效 07-28
- SkillSpector 怎么安装?AI Agent 技能包安全检测教程 07-28
- 2026年类似三角洲行动的高人气战术射击游戏推荐 07-28
- 三角洲行动S10新赛季上线时间一览 07-28
- 三角洲行动工程型干员液氮技能解析及实战表现评测 07-28
- 三角洲行动账号购买平台指南:安全靠谱的买号渠道汇总 07-28