0

0

如何在Golang中利用Copy函数复制切片 Go语言深拷贝与浅拷贝区别

P粉602998670

P粉602998670

发布时间:2026-03-11 10:56:32

|

181人浏览过

|

来源于php中文网

原创

go 的 copy 函数仅浅拷贝,不递归处理引用类型;深拷贝需手动实现或用第三方库,判断依据是数据生命周期与并发修改需求。

如何在golang中利用copy函数复制切片 go语言深拷贝与浅拷贝区别

Go 里 copy 函数只能做浅拷贝,别指望它复制嵌套结构

copy 函数只复制顶层元素的值,对切片、map、指针、struct 字段里的引用类型完全不递归处理。比如你有一个 []*int[]struct{ Name string; Data []byte }copy 后新切片里的指针或子切片仍指向原内存地址。

常见错误现象:
修改副本中某个 struct 的 Data 字段,原切片对应项也跟着变;或者把副本传给 goroutine 后,主线程改了原切片底层数组,导致数据竞争。

  • 适用场景:纯值类型切片(如 []int[]string)的快速复制,或已知内部无引用需隔离的场景
  • 参数差异:copy(dst, src) 要求 dst 可寻址且长度 ≥ src 长度,否则只复制到 dst 容量上限
  • 性能影响:零分配、O(n) 时间,但掩盖了共享风险 —— 看似快,出问题更难查

深拷贝必须手动实现或借助第三方库,标准库不提供

Go 没有类似 Python 的 copy.deepcopy 或 Java 的序列化克隆机制。反射能做但开销大、不安全(比如无法处理 unexported 字段)、且不能跨包处理私有结构。

使用场景取决于数据结构复杂度:

立即学习go语言免费学习笔记(深入)”;

Video Ocean
Video Ocean

人人皆导演,让视频创作变得轻松自如

下载
  • 简单 struct + 值类型字段:直接赋值(new := old)就足够,本质是深拷贝
  • 含 slice/map/ptr 的 struct:必须逐字段处理,尤其注意 map 要用 make + for range 重建,slicemake + copy
  • 嵌套多层或动态结构:考虑 gob 编码解码(注意性能和字段导出限制),或用 github.com/jinzhu/copier 这类轻量库(它用反射,但跳过私有字段并支持 tag 控制)

示例(安全的手动深拷贝):

func deepCopySliceOfStructs(src []Item) []Item {
	dst := make([]Item, len(src))
	for i := range src {
		dst[i] = src[i] // Item 是全值类型字段才成立
	}
	return dst
}

切片复制时底层数组共享是默认行为,不是 bug 是设计

Go 切片本质是三元组:{ptr, len, cap}copyappend、甚至 s[1:3] 子切片,只要没触发扩容,都可能复用同一底层数组。这是性能关键,但也意味着「副本」未必独立。

容易踩的坑:

  • 把函数内局部切片返回后,在外面继续 append —— 可能意外改到其他变量共享的底层数组
  • copy(dst[:0], src) 清空再填,但 dst 容量很大,后续 append 仍在原数组上扩,污染上游
  • 并发读写同一底层数组的不同切片,没加锁 → data race(go run -race 能抓到)

解决思路:需要隔离时,显式创建新底层数组:

newSlice := make([]T, len(old))
copy(newSlice, old)
或用 append([]T(nil), old...)(更简洁,但语义稍隐晦)

什么时候该用深拷贝?看数据生命周期和所有权边界

不是所有复制都需要深拷贝。核心判断依据是:副本是否会在原数据失效后继续使用,或是否会被并发修改。

  • HTTP handler 中接收 JSON 解析出的 []User,转给异步任务处理 → 必须深拷贝,避免 handler 返回后底层内存被 GC 或重用
  • 配置切片在 init 阶段生成,只读全局使用 → 浅拷贝够用,甚至直接共享
  • goroutine 间传递切片且只读 → 加 sync.RWMutex 比深拷贝更高效

最易被忽略的一点:深拷贝本身不解决竞态,只是移除共享。如果深拷贝后的数据又被多个 goroutine 无锁读写,问题照旧。真正的边界在于「谁负责修改」和「修改是否可预期」。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
golang如何定义变量
golang如何定义变量

golang定义变量的方法:1、声明变量并赋予初始值“var age int =值”;2、声明变量但不赋初始值“var age int”;3、使用短变量声明“age :=值”等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

210

2024.02.23

golang有哪些数据转换方法
golang有哪些数据转换方法

golang数据转换方法:1、类型转换操作符;2、类型断言;3、字符串和数字之间的转换;4、JSON序列化和反序列化;5、使用标准库进行数据转换;6、使用第三方库进行数据转换;7、自定义数据转换函数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

247

2024.02.23

golang常用库有哪些
golang常用库有哪些

golang常用库有:1、标准库;2、字符串处理库;3、网络库;4、加密库;5、压缩库;6、xml和json解析库;7、日期和时间库;8、数据库操作库;9、文件操作库;10、图像处理库。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

356

2024.02.23

golang和python的区别是什么
golang和python的区别是什么

golang和python的区别是:1、golang是一种编译型语言,而python是一种解释型语言;2、golang天生支持并发编程,而python对并发与并行的支持相对较弱等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

214

2024.03.05

golang是免费的吗
golang是免费的吗

golang是免费的。golang是google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的开源编程语言,采用bsd开源协议。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

409

2024.05.21

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

490

2025.06.09

golang相关判断方法
golang相关判断方法

本专题整合了golang相关判断方法,想了解更详细的相关内容,请阅读下面的文章。

200

2025.06.10

golang数组使用方法
golang数组使用方法

本专题整合了golang数组用法,想了解更多的相关内容,请阅读专题下面的文章。

1438

2025.06.17

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

3

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 6.1万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号