GO 中的深拷贝和浅拷贝
数组的深浅拷贝
-
浅拷贝(Shallow Copy): 浅拷贝只是复制了数据结构的引用,而不是复制数据结构本身。这意味着新的数据结构和原始数据结构共享相同的底层数据。如果修改了其中一个数据结构,另一个数据结构也会受到影响。浅拷贝通常是通过直接赋值或者切片操作来实现的。
// 浅拷贝示例 slice1 := []int{1, 2, 3} slice2 := slice1 // 浅拷贝
在上面的示例中,
slice2
是slice1
的浅拷贝,它们共享相同的底层数组。 -
深拷贝(Deep Copy): 深拷贝会复制整个数据结构,包括其所有的子数据结构,从而创建一个完全独立的副本。这意味着新的数据结构和原始数据结构是完全独立的,彼此不受影响。深拷贝通常需要递归地复制数据结构的所有子结构。
// 深拷贝示例 slice1 := []int{1, 2, 3} slice2 := make([]int, len(slice1)) copy(slice2, slice1) // 深拷贝
在上面的示例中,通过使用
copy
函数将slice1
的内容复制到了一个新的切片slice2
中,这样就实现了深拷贝。
结构体的深拷贝
在 Go 中,结构体的深拷贝通常需要手动编写代码来实现,因为结构体的复制通常只是浅拷贝。深拷贝需要递归地复制结构体的所有字段,包括其中包含的其他结构体字段。
以下是一个示例,演示了如何对结构体进行深拷贝:
package main
import (
"fmt"
"reflect"
)
// 定义一个结构体
type Person struct {
Name string
Age int
Address Address
}
type Address struct {
City string
State string
}
// 实现一个深拷贝函数
func DeepCopy(src interface{}) interface{} {
srcValue := reflect.ValueOf(src)
// 获取原始结构体类型
srcType := reflect.TypeOf(src)
// 创建一个与原始结构体类型相同的新结构体变量
dst := reflect.New(srcType).Elem()
// 遍历原始结构体的字段
for i := 0; i < srcValue.NumField(); i++ {
field := srcValue.Field(i)
// 如果字段是结构体类型,则递归进行深拷贝
if field.Kind() == reflect.Struct {
fieldValue := DeepCopy(field.Interface())
dst.Field(i).Set(reflect.ValueOf(fieldValue))
} else {
// 如果字段是基本类型,则直接复制值
dst.Field(i).Set(field)
}
}
return dst.Interface()
}
func main() {
// 创建一个原始结构体
person1 := Person{
Name: "Alice",
Age: 30,
Address: Address{
City: "New York",
State: "NY",
},
}
// 对原始结构体进行深拷贝
person2 := DeepCopy(person1).(Person)
// 修改深拷贝后的结构体
person2.Name = "Bob"
person2.Age = 40
person2.Address.City = "Los Angeles"
// 打印原始结构体和深拷贝后的结构体
fmt.Println("Original struct:", person1)
fmt.Println("Deep copied struct:", person2)
}
在上面的示例中,我们定义了一个 Person
结构体和一个 Address
结构体。然后,我们实现了一个名为 DeepCopy
的函数,用于对结构体进行深拷贝。该函数使用了反射来处理结构体的字段,对字段进行递归的深拷贝。最后,我们创建了一个原始结构体 person1
,并通过 DeepCopy
函数对其进行了深拷贝,得到了 person2
。通过打印结果,我们可以看到原始结构体和深拷贝后的结构体是独立的,彼此不受影响。
转载自:https://juejin.cn/post/7359893253170774052