deepcopy.go 3.4 KB

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