123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- // 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
- }
|