github.com/songzhibin97/gkit@v1.2.13/tools/deepcopy/deepcopy.go (about) 1 package deepcopy 2 3 import ( 4 "github.com/songzhibin97/gkit/tools" 5 "reflect" 6 ) 7 8 func deepCopy(dst, src reflect.Value) { 9 switch src.Kind() { 10 case reflect.Interface: 11 value := src.Elem() 12 if !value.IsValid() { 13 return 14 } 15 newValue := reflect.New(value.Type()).Elem() 16 deepCopy(newValue, value) 17 dst.Set(newValue) 18 case reflect.Ptr: 19 value := src.Elem() 20 if !value.IsValid() { 21 return 22 } 23 dst.Set(reflect.New(value.Type())) 24 deepCopy(dst.Elem(), value) 25 case reflect.Map: 26 dst.Set(reflect.MakeMap(src.Type())) 27 keys := src.MapKeys() 28 for _, key := range keys { 29 value := src.MapIndex(key) 30 newValue := reflect.New(value.Type()).Elem() 31 deepCopy(newValue, value) 32 dst.SetMapIndex(key, newValue) 33 } 34 case reflect.Slice: 35 dst.Set(reflect.MakeSlice(src.Type(), src.Len(), src.Cap())) 36 for i := 0; i < src.Len(); i++ { 37 deepCopy(dst.Index(i), src.Index(i)) 38 } 39 case reflect.Struct: 40 typeSrc := src.Type() 41 for i := 0; i < src.NumField(); i++ { 42 value := src.Field(i) 43 tag := typeSrc.Field(i).Tag 44 if value.CanSet() && tag.Get("gkit") != "-" { 45 deepCopy(dst.Field(i), value) 46 } 47 } 48 default: 49 dst.Set(src) 50 } 51 } 52 53 func DeepCopy(dst, src interface{}) error { 54 dstT, srcT := reflect.TypeOf(dst), reflect.TypeOf(src) 55 if dstT != srcT { 56 return tools.ErrorNoEquals 57 } 58 if srcT.Kind() != reflect.Ptr { 59 return tools.ErrorMustPtr 60 } 61 dstV, srcV := reflect.ValueOf(dst).Elem(), reflect.ValueOf(src).Elem() 62 if !dstV.IsValid() || !srcV.IsValid() { 63 return tools.ErrorInvalidValue 64 } 65 deepCopy(dstV, srcV) 66 return nil 67 } 68 69 func Clone(v interface{}) interface{} { 70 dst := reflect.New(reflect.TypeOf(v).Elem()) 71 deepCopy(dst, reflect.ValueOf(v)) 72 return dst.Interface() 73 }