深拷贝
1
拷贝的是数据本身,创造一个新对象,新创建的对象与原对象不共享内存,新创建的对象在内存中开辟一个新的内存地址,新对象值修改时不会影响原对象值
浅拷贝
1
浅拷贝:拷贝的是数据地址,只复制指向的对象的指针,此时新对象和老对象指向的内存地址是一样的,新对象值修改时老对象也会变化
- Go实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44func DeepCopy(data interface{}) interface{} {
dataType := reflect.TypeOf(data)
dataValue := reflect.ValueOf(data)
// 如果是指针类型,获取指针指向的值
if dataType.Kind() == reflect.Ptr {
dataType = dataType.Elem()
dataValue = dataValue.Elem()
}
switch dataType.Kind() {
case reflect.Map:
copied := reflect.MakeMap(dataType)
mapKeys := dataValue.MapKeys()
for _, key := range mapKeys {
value := dataValue.MapIndex(key)
copiedValue := DeepCopy(value.Interface())
// 这步大部分情况下如需考虑,因为基本没人会使用引用类型的key
copiedKey := reflect.ValueOf(DeepCopy(key.Interface()))
copied.SetMapIndex(copiedKey, reflect.ValueOf(copiedValue))
}
return copied.Interface()
case reflect.Slice:
copied := reflect.MakeSlice(dataType, dataValue.Len(), dataValue.Len())
for i := 0; i < dataValue.Len(); i++ {
element := dataValue.Index(i)
copiedElement := DeepCopy(element.Interface())
copied.Index(i).Set(reflect.ValueOf(copiedElement))
}
return copied.Interface()
case reflect.Struct:
copied := reflect.New(dataType).Elem()
for i := 0; i < dataType.NumField(); i++ {
fieldType := dataType.Field(i)
fieldValue := dataValue.Field(i)
// 如果字段是可导出的(大写开头),则进行深拷贝
if fieldType.PkgPath == "" {
copiedField := DeepCopy(fieldValue.Interface())
copied.Field(i).Set(reflect.ValueOf(copiedField))
}
}
return copied.Interface()
default:
return data
}
}