123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- // 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"
- // _ "github.com/stretchr/testify/assert"
- )
- // Interface for delegating copy process to type
- type DeepCopyer interface {
- DeepCopy() interface{}
- }
- // // Iface is an alias to Copy; this exists for backwards compatibility reasons.
- // func Iface(iface interface{}) interface{} {
- // return Copy(iface)
- // }
- // 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.
- // 只支持常规类型的复制,例如:简单类型,时间,map,slice,array,指针,结构体及结构体
- // 不要用于有循环引用的数据
- // 多个指针指向同一个变量,复制后会生成多个
- // 未导出类型不复制;
- func Copy(src interface{}) interface{} {
- if src == nil {
- return 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()
- // Recursively copy the original.
- deep := 0
- err := copyRecursive(original, cpy, deep)
- if err != nil {
- panic(err)
- }
- // Return the copy as an interface.
- return cpy.Interface()
- }
- // copyRecursive does the actual copying of the interface. It currently has
- // limited support for what it can handle. Add as needed.
- // 支持:简单类型,时间,map,slice,array,指针,结构体及结构体匿名变量;
- // 其他不支持(reflect.Chan, reflect.Func, reflect.Invalid, reflect.UnsafePointer)
- // 未导出类型不复制;
- // 多个指针指向同一个变量,复制后会生成多个
- // 不要用于有循环引用的数据,深度只能防死循环,不能防重复构造;
- // noCopy结构未处理
- // original 类型值
- // cpy 新类型值 指针的解引用
- func copyRecursive(original, cpy reflect.Value, deep int) error {
- deep += 1
- if deep > 20 {
- return errors.New("max deep")
- }
- // check for implement deepcopy.Interface
- if original.CanInterface() {
- if copier, ok := original.Interface().(DeepCopyer); ok {
- cpy.Set(reflect.ValueOf(copier.DeepCopy()))
- return nil
- }
- }
- // fmt.Println(original.Type().Name(), original.Type().String())
- var err error
- // handle according to original's Kind
- switch original.Kind() {
- case reflect.Ptr:
- // Get the actual value being pointed to.
- originalValue := original.Elem()
- // if it isn't valid, return.
- if !originalValue.IsValid() {
- return nil
- }
- cpy.Set(reflect.New(originalValue.Type()))
- err = copyRecursive(originalValue, cpy.Elem(), deep)
- case reflect.Interface:
- // If this is a nil, don't do anything
- if original.IsNil() {
- return nil
- }
- // Get the value for the interface, not the pointer.
- originalValue := original.Elem()
- // Get the value by calling Elem().
- copyValue := reflect.New(originalValue.Type()).Elem()
- err = copyRecursive(originalValue, copyValue, deep)
- 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
- }
- // Go through each field of the struct and copy it.
- num := original.NumField()
- for i := 0; i < num; i++ {
- if !oriType.Field(i).IsExported() {
- continue
- }
- err = copyRecursive(original.Field(i), cpy.Field(i), deep)
- if err != nil {
- break
- }
- }
- case reflect.Slice:
- if original.IsNil() {
- return nil
- }
- // Make a new slice and copy each element.
- cpy.Set(reflect.MakeSlice(original.Type(), original.Len(), original.Cap()))
- for i := 0; i < original.Len(); i++ {
- err = copyRecursive(original.Index(i), cpy.Index(i), deep)
- if err != nil {
- break
- }
- }
- 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(originalValue, copyValue, deep)
- if err != nil {
- break
- }
- copyKey := reflect.New(key.Type()).Elem()
- err = copyRecursive(key, copyKey, deep)
- if err != nil {
- break
- }
- cpy.SetMapIndex(copyKey, copyValue)
- }
- case reflect.Array:
- for i := 0; i < original.Len(); i++ {
- copyRecursive(original.Index(i), cpy.Index(i), deep)
- }
- case reflect.Uintptr, reflect.Chan, reflect.Func, reflect.Invalid, reflect.UnsafePointer:
- return nil
- default:
- cpy.Set(original)
- }
- return err
- }
|