deepcopy.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. package utils
  2. import (
  3. "reflect"
  4. "time"
  5. )
  6. // Interface for delegating copy process to type
  7. type Interface interface {
  8. DeepCopy() interface{}
  9. }
  10. // Iface is an alias to Copy; this exists for backwards compatibility reasons.
  11. func Iface(iface interface{}) interface{} {
  12. return Copy(iface)
  13. }
  14. // Copy creates a deep copy of whatever is passed to it and returns the copy
  15. // in an interface{}. The returned value will need to be asserted to the
  16. // correct type.
  17. func Copy(src interface{}) interface{} {
  18. if src == nil {
  19. return nil
  20. }
  21. // Make the interface a reflect.Value
  22. original := reflect.ValueOf(src)
  23. // Make a copy of the same type as the original.
  24. cpy := reflect.New(original.Type()).Elem()
  25. // Recursively copy the original.
  26. copyRecursive(original, cpy)
  27. // Return the copy as an interface.
  28. return cpy.Interface()
  29. }
  30. // copyRecursive does the actual copying of the interface. It currently has
  31. // limited support for what it can handle. Add as needed.
  32. func copyRecursive(original, cpy reflect.Value) {
  33. // check for implement deepcopy.Interface
  34. if original.CanInterface() {
  35. if copier, ok := original.Interface().(Interface); ok {
  36. cpy.Set(reflect.ValueOf(copier.DeepCopy()))
  37. return
  38. }
  39. }
  40. // handle according to original's Kind
  41. switch original.Kind() {
  42. case reflect.Ptr:
  43. // Get the actual value being pointed to.
  44. originalValue := original.Elem()
  45. // if it isn't valid, return.
  46. if !originalValue.IsValid() {
  47. return
  48. }
  49. cpy.Set(reflect.New(originalValue.Type()))
  50. copyRecursive(originalValue, cpy.Elem())
  51. case reflect.Interface:
  52. // If this is a nil, don't do anything
  53. if original.IsNil() {
  54. return
  55. }
  56. // Get the value for the interface, not the pointer.
  57. originalValue := original.Elem()
  58. // Get the value by calling Elem().
  59. copyValue := reflect.New(originalValue.Type()).Elem()
  60. copyRecursive(originalValue, copyValue)
  61. cpy.Set(copyValue)
  62. case reflect.Struct:
  63. t, ok := original.Interface().(time.Time)
  64. if ok {
  65. cpy.Set(reflect.ValueOf(t))
  66. return
  67. }
  68. // Go through each field of the struct and copy it.
  69. for i := 0; i < original.NumField(); i++ {
  70. // The Type's StructField for a given field is checked to see if StructField.PkgPath
  71. // is set to determine if the field is exported or not because CanSet() returns false
  72. // for settable fields. I'm not sure why. -mohae
  73. if original.Type().Field(i).PkgPath != "" {
  74. continue
  75. }
  76. copyRecursive(original.Field(i), cpy.Field(i))
  77. }
  78. case reflect.Slice:
  79. if original.IsNil() {
  80. return
  81. }
  82. // Make a new slice and copy each element.
  83. cpy.Set(reflect.MakeSlice(original.Type(), original.Len(), original.Cap()))
  84. for i := 0; i < original.Len(); i++ {
  85. copyRecursive(original.Index(i), cpy.Index(i))
  86. }
  87. case reflect.Map:
  88. if original.IsNil() {
  89. return
  90. }
  91. cpy.Set(reflect.MakeMap(original.Type()))
  92. for _, key := range original.MapKeys() {
  93. originalValue := original.MapIndex(key)
  94. copyValue := reflect.New(originalValue.Type()).Elem()
  95. copyRecursive(originalValue, copyValue)
  96. copyKey := Copy(key.Interface())
  97. cpy.SetMapIndex(reflect.ValueOf(copyKey), copyValue)
  98. }
  99. default:
  100. cpy.Set(original)
  101. }
  102. }