// deepcopy makes deep copies of things. A standard copy will copy the // pointers: deep copy copies the values pointed to. Unexported field // values are not copied. // // Copyright (c)2014-2016, Joel Scoble (github.com/mohae), all rights reserved. // License: MIT, for more details check the included LICENSE file. package deepcopy import ( "errors" "reflect" "time" ) // copyContext 用于追踪已复制的对象,避免循环引用 type copyContext struct { seen map[uintptr]reflect.Value deep int } // Interface for delegating copy process to type type DeepCopyer interface { DeepCopy() interface{} } // Copy creates a deep copy of whatever is passed to it and returns the copy // in an interface{}. The returned value will need to be asserted to the // correct type. // 支持以下类型的复制: // - 简单类型(int, string 等) // - 时间类型 (time.Time) // - 复合类型(map, slice, array) // - 指针类型 // - 结构体(包含匿名字段) // // 特性: // - 支持循环引用检测 // - 未导出字段不会被复制 // - 实现了 DeepCopyer 接口的类型可以自定义复制行为 // - 不支持的类型(Channel、Function等)会被跳过,不影响其他数据的复制 // // 限制: // - 递归深度限制为20层 // - 不支持的类型(Channel、Function等)会被跳过不处理 func Copy(src interface{}) (interface{}, error) { if src == nil { return nil, nil } // Make the interface a reflect.Value original := reflect.ValueOf(src) // Make a copy of the same type as the original. cpy := reflect.New(original.Type()).Elem() // Create a new context for tracking copied objects ctx := ©Context{ seen: make(map[uintptr]reflect.Value), deep: 0, } // Recursively copy the original. if err := copyRecursive(ctx, original, cpy); err != nil { return nil, err } // Return the copy as an interface. return cpy.Interface(), nil } // isUnsupportedType checks if the given type is unsupported for deep copy func isUnsupportedType(k reflect.Kind) bool { switch k { case reflect.Chan, reflect.Func, reflect.UnsafePointer, reflect.Invalid: return true } return false } // copyRecursive does the actual copying of the interface. // 支持的类型: // - 简单类型 // - 时间类型 (time.Time) // - map, slice, array // - 指针 // - 结构体及其匿名字段 // // 特性: // - 使用 copyContext 处理循环引用 // - 未导出字段会被跳过 // - 支持 noCopy 标记的结构体 // - 不支持的类型会被跳过不处理 // // 参数: // - ctx: 复制上下文,用于追踪已复制的对象 // - original: 原始值 // - cpy: 目标值(指针的解引用) func copyRecursive(ctx *copyContext, original, cpy reflect.Value) error { ctx.deep++ if ctx.deep > 20 { return errors.New("max recursion depth exceeded") } defer func() { ctx.deep-- }() // Handle nil pointer if !original.IsValid() { return nil } // 对不支持的类型直接跳过 if isUnsupportedType(original.Kind()) { return nil } // Check for circular references if original.Kind() == reflect.Ptr || original.Kind() == reflect.Interface { if original.Kind() == reflect.Ptr { ptr := original.Pointer() if copied, ok := ctx.seen[ptr]; ok { cpy.Set(copied) return nil } if !original.IsNil() { ctx.seen[ptr] = cpy } } } // check for implement deepcopy.Interface if original.CanInterface() { if copier, ok := original.Interface().(DeepCopyer); ok { cpy.Set(reflect.ValueOf(copier.DeepCopy())) return nil } } var err error switch original.Kind() { case reflect.Ptr: originalValue := original.Elem() if !originalValue.IsValid() { return nil } cpy.Set(reflect.New(originalValue.Type())) err = copyRecursive(ctx, originalValue, cpy.Elem()) case reflect.Interface: if original.IsNil() { return nil } originalValue := original.Elem() copyValue := reflect.New(originalValue.Type()).Elem() err = copyRecursive(ctx, originalValue, copyValue) if err == nil { cpy.Set(copyValue) } case reflect.Struct: t, ok := original.Interface().(time.Time) if ok { cpy.Set(reflect.ValueOf(t)) return nil } oriType := original.Type() if _, ok := oriType.FieldByName("noCopy"); ok { return nil } for i := 0; i < original.NumField(); i++ { if !oriType.Field(i).IsExported() { continue } err = copyRecursive(ctx, original.Field(i), cpy.Field(i)) if err != nil { // 忽略不支持类型的错误 continue } } case reflect.Slice: if original.IsNil() { return nil } cpy.Set(reflect.MakeSlice(original.Type(), original.Len(), original.Cap())) for i := 0; i < original.Len(); i++ { err = copyRecursive(ctx, original.Index(i), cpy.Index(i)) if err != nil { // 忽略不支持类型的错误 continue } } case reflect.Map: if original.IsNil() { return nil } cpy.Set(reflect.MakeMap(original.Type())) for _, key := range original.MapKeys() { originalValue := original.MapIndex(key) copyValue := reflect.New(originalValue.Type()).Elem() err = copyRecursive(ctx, originalValue, copyValue) if err != nil { // 忽略不支持类型的错误 continue } copyKey := reflect.New(key.Type()).Elem() err = copyRecursive(ctx, key, copyKey) if err != nil { // 忽略不支持类型的错误 continue } cpy.SetMapIndex(copyKey, copyValue) } case reflect.Array: for i := 0; i < original.Len(); i++ { err = copyRecursive(ctx, original.Index(i), cpy.Index(i)) if err != nil { // 忽略不支持类型的错误 continue } } default: cpy.Set(original) } // 只返回非不支持类型的错误 if err != nil && err.Error() != "max recursion depth exceeded" { return nil } return err }