
在 Go 语言中,深拷贝(Deep Copy)指的是创建一个新对象,其字段值与原对象相同,且所有嵌套的引用类型(如 slice、map、指针等)也被递归复制,而不是共享引用。理解深拷贝的关键在于区分值类型和指针类型的复制行为。
Go 中的赋值操作默认是“浅复制”(Shallow Copy),具体行为取决于字段类型:
例如:
type Person struct {
Name string
Tags []string
Info *Detail
}
type Detail struct {
Age int
}
original := Person{
Name: "Alice",
Tags: []string{"go", "dev"},
Info: &Detail{Age: 30},
}
// 浅拷贝
copy := original此时:
立即学习“go语言免费学习笔记(深入)”;
copy.Name
copy.Tags
original.Tags
copy.Info
original.Info
Detail
修改
copy.Tags[0]
copy.Info.Age
original
对每个引用类型字段手动创建新实例并复制内容。
func DeepCopy(p Person) Person {
var tagsCopy []string
if p.Tags != nil {
tagsCopy = make([]string, len(p.Tags))
copy(tagsCopy, p.Tags)
}
var infoCopy *Detail
if p.Info != nil {
temp := *p.Info
infoCopy = &temp
}
return Person{
Name: p.Name,
Tags: tagsCopy,
Info: infoCopy,
}
}这种方式控制精细,性能好,适合字段明确、结构不复杂的类型。
利用 Go 的 gob 包进行序列化再反序列化,实现“伪深拷贝”。
import "bytes"
import "encoding/gob"
func DeepCopyGob[T any](src T) (T, error) {
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
dec := gob.NewDecoder(&buf)
if err := enc.Encode(src); err != nil {
return src, err
}
var copy T
if err := dec.Decode(©); err != nil {
return src, err
}
return copy, nil
}注意:
例如使用 github.com/jinzhu/copier:
import "github.com/jinzhu/copier" var copy Person copier.Copy(©, &original)
这类库通常处理常见场景,但行为可能不完全符合预期(如 slice 处理方式),需仔细测试。
| 场景 | 复制方式 | 是否共享数据 | 示例 |
|---|---|---|---|
| 值类型字段(int、string) | 直接赋值 | 否 | 修改副本不影响原值 |
| slice 字段 | 直接赋值 | 是(底层数组共享) | 修改元素互相影响 |
| map 字段 | 直接赋值 | 是 | 修改键值互相影响 |
| 指针字段(*T) | 直接赋值 | 是(指向同一对象) | 修改结构体字段互相影响 |
| 嵌套 struct(值类型) | 直接赋值 | 否(但内部引用类型仍共享) | 需递归处理 |
关键点:即使 struct 字段是值类型,只要它内部包含引用类型(如 slice、map),直接赋值仍会导致共享。
基本上就这些。深拷贝在 Go 中没有语言级支持,必须根据场景选择合适策略,理解指针和引用类型的复制机制是关键。
以上就是如何实现Golang的深拷贝操作 对比指针与值类型的复制行为的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号