package clones import "reflect" func deepCopy(dst, src reflect.Value) { switch src.Kind() { case reflect.Interface: value := src.Elem() if !value.IsValid() { return } newValue := reflect.New(value.Type()).Elem() deepCopy(newValue, value) dst.Set(newValue) case reflect.Ptr: value := src.Elem() if !value.IsValid() { return } dst.Set(reflect.New(value.Type())) deepCopy(dst.Elem(), value) case reflect.Map: dst.Set(reflect.MakeMap(src.Type())) keys := src.MapKeys() for _, key := range keys { value := src.MapIndex(key) newValue := reflect.New(value.Type()).Elem() deepCopy(newValue, value) dst.SetMapIndex(key, newValue) } case reflect.Slice: dst.Set(reflect.MakeSlice(src.Type(), src.Len(), src.Cap())) for i := 0; i < src.Len(); i++ { deepCopy(dst.Index(i), src.Index(i)) } case reflect.Struct: typeSrc := src.Type() for i := 0; i < src.NumField(); i++ { value := src.Field(i) tag := typeSrc.Field(i).Tag if value.CanSet() && tag.Get("deepcopy") != "-" { deepCopy(dst.Field(i), value) } } default: dst.Set(src) } } // DeepCopy 深拷贝 func DeepCopy(dst, src interface{}) { typeDst := reflect.TypeOf(dst) typeSrc := reflect.TypeOf(src) if typeDst != typeSrc { panic("DeepCopy: " + typeDst.String() + " != " + typeSrc.String()) } if typeSrc.Kind() != reflect.Ptr { panic("DeepCopy: pass arguments by address") } valueDst := reflect.ValueOf(dst).Elem() valueSrc := reflect.ValueOf(src).Elem() if !valueDst.IsValid() || !valueSrc.IsValid() { panic("DeepCopy: invalid arguments") } deepCopy(valueDst, valueSrc) } // DeepClone 深克隆 func DeepClone(v interface{}) interface{} { dst := reflect.New(reflect.TypeOf(v)).Elem() deepCopy(dst, reflect.ValueOf(v)) return dst.Interface() }