...
1
2
3
4
5
6
7 package deepcopy
8
9 import (
10 "reflect"
11 "time"
12 )
13
14
15 type Interface interface {
16 DeepCopy() interface{}
17 }
18
19
20 func Iface(iface interface{}) interface{} {
21 return Copy(iface)
22 }
23
24
25
26
27 func Copy(src interface{}) interface{} {
28 if src == nil {
29 return nil
30 }
31
32
33 original := reflect.ValueOf(src)
34
35
36 cpy := reflect.New(original.Type()).Elem()
37
38
39 copyRecursive(original, cpy)
40
41
42 return cpy.Interface()
43 }
44
45
46
47 func copyRecursive(original, cpy reflect.Value) {
48
49 if original.CanInterface() {
50 if copier, ok := original.Interface().(Interface); ok {
51 cpy.Set(reflect.ValueOf(copier.DeepCopy()))
52 return
53 }
54 }
55
56
57 switch original.Kind() {
58 case reflect.Ptr:
59
60 originalValue := original.Elem()
61
62
63 if !originalValue.IsValid() {
64 return
65 }
66 cpy.Set(reflect.New(originalValue.Type()))
67 copyRecursive(originalValue, cpy.Elem())
68
69 case reflect.Interface:
70
71 if original.IsNil() {
72 return
73 }
74
75 originalValue := original.Elem()
76
77
78 copyValue := reflect.New(originalValue.Type()).Elem()
79 copyRecursive(originalValue, copyValue)
80 cpy.Set(copyValue)
81
82 case reflect.Struct:
83 t, ok := original.Interface().(time.Time)
84 if ok {
85 cpy.Set(reflect.ValueOf(t))
86 return
87 }
88
89 for i := 0; i < original.NumField(); i++ {
90
91
92
93 if original.Type().Field(i).PkgPath != "" {
94 continue
95 }
96 copyRecursive(original.Field(i), cpy.Field(i))
97 }
98
99 case reflect.Slice:
100 if original.IsNil() {
101 return
102 }
103
104 cpy.Set(reflect.MakeSlice(original.Type(), original.Len(), original.Cap()))
105 for i := 0; i < original.Len(); i++ {
106 copyRecursive(original.Index(i), cpy.Index(i))
107 }
108
109 case reflect.Map:
110 if original.IsNil() {
111 return
112 }
113 cpy.Set(reflect.MakeMap(original.Type()))
114 for _, key := range original.MapKeys() {
115 originalValue := original.MapIndex(key)
116 copyValue := reflect.New(originalValue.Type()).Elem()
117 copyRecursive(originalValue, copyValue)
118 copyKey := Copy(key.Interface())
119 cpy.SetMapIndex(reflect.ValueOf(copyKey), copyValue)
120 }
121
122 default:
123 cpy.Set(original)
124 }
125 }
126
View as plain text