package copier import ( "reflect" "sync" ) type copier struct { opt *options visited map[uintptr]struct{} mu sync.Mutex } func New(opts ...option) *copier { opt := getOpt(opts...) var visited map[uintptr]struct{} if opt.detectCircularRefs { visited = make(map[uintptr]struct{}) } return &copier{ visited: visited, opt: opt, } } func (c *copier) Copy(dst, src any) error { c.mu.Lock() defer c.reset() defer c.mu.Unlock() if dst == nil || src == nil { return ErrInvalidCopyDestination } srcValue, dstValue := indirect(reflect.ValueOf(src)), indirect(reflect.ValueOf(dst)) if !srcValue.IsValid() { return ErrInvalidCopyFrom } if !dstValue.CanSet() { return ErrInvalidCopyDestination } return c.deepCopy(dstValue, srcValue, 0) } func (c *copier) reset() { if c.opt.detectCircularRefs { clear(c.visited) } } func (c *copier) deepCopy(dst, src reflect.Value, depth int) error { if c.ExceedMaxDepth(depth) { return ErrMaxDepthExceeded } // 复制源无效,直接返回 if !src.IsValid() { return nil } // 对于 slice 和 map,如果 src 是 nil,不复制(保持 dst 不变) // 对于其他类型(如 string),即使 IsZero 也要复制 switch src.Kind() { case reflect.Slice, reflect.Map: if src.IsNil() { return nil } } if c.isCircularRefs(src) { return ErrCircularReference } // 可以直接赋值时直接赋值并返回 srcType, dstType := src.Type(), dst.Type() // 处理时间类型 if isTimeType(srcType) || isTimeType(dstType) { return c.copyTime(dst, src) } // fmt.Println("srcType:", srcType, src.Kind().String(), "dstType:", dstType, dst.Kind().String()) switch src.Kind() { case reflect.Slice, reflect.Array: return c.copySliceOrArray(dst, src, depth) case reflect.Map: return c.copyMap(dst, src, depth) case reflect.Struct: return c.copyStruct(dst, src, depth) case reflect.Pointer: return c.copyPointer(dst, src, depth) case reflect.Interface: return c.copyInterface(dst, src, depth) case reflect.Chan, reflect.Func, reflect.UnsafePointer: return ErrNotSupported(srcType, dstType) default: return c.copyBasic(dst, src) } }