deepcopy.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
  2. //
  3. // This Source Code Form is subject to the terms of the MIT License.
  4. // If a copy of the MIT was not distributed with this file,
  5. // You can obtain one at https://github.com/gogf/gf.
  6. // Package deepcopy makes deep copies of things using reflection.
  7. //
  8. // This package is maintained from: https://github.com/mohae/deepcopy
  9. package deepcopy
  10. import (
  11. "reflect"
  12. "time"
  13. )
  14. // Interface for delegating copy process to type
  15. type Interface interface {
  16. DeepCopy() interface{}
  17. }
  18. // Copy creates a deep copy of whatever is passed to it and returns the copy
  19. // in an interface{}. The returned value will need to be asserted to the
  20. // correct type.
  21. func Copy(src interface{}) interface{} {
  22. if src == nil {
  23. return nil
  24. }
  25. // Copy by type assertion.
  26. switch r := src.(type) {
  27. case
  28. int, int8, int16, int32, int64,
  29. uint, uint8, uint16, uint32, uint64,
  30. float32, float64,
  31. complex64, complex128,
  32. string,
  33. bool:
  34. return r
  35. default:
  36. if v, ok := src.(Interface); ok {
  37. return v.DeepCopy()
  38. }
  39. var (
  40. original = reflect.ValueOf(src) // Make the interface a reflect.Value
  41. dst = reflect.New(original.Type()).Elem() // Make a copy of the same type as the original.
  42. )
  43. // Recursively copy the original.
  44. copyRecursive(original, dst)
  45. // Return the copy as an interface.
  46. return dst.Interface()
  47. }
  48. }
  49. // copyRecursive does the actual copying of the interface. It currently has
  50. // limited support for what it can handle. Add as needed.
  51. func copyRecursive(original, cpy reflect.Value) {
  52. // check for implement deepcopy.Interface
  53. if original.CanInterface() && original.IsValid() && !original.IsZero() {
  54. if copier, ok := original.Interface().(Interface); ok {
  55. cpy.Set(reflect.ValueOf(copier.DeepCopy()))
  56. return
  57. }
  58. }
  59. // handle according to original's Kind
  60. switch original.Kind() {
  61. case reflect.Ptr:
  62. // Get the actual value being pointed to.
  63. originalValue := original.Elem()
  64. // if it isn't valid, return.
  65. if !originalValue.IsValid() {
  66. return
  67. }
  68. cpy.Set(reflect.New(originalValue.Type()))
  69. copyRecursive(originalValue, cpy.Elem())
  70. case reflect.Interface:
  71. // If this is a nil, don't do anything
  72. if original.IsNil() {
  73. return
  74. }
  75. // Get the value for the interface, not the pointer.
  76. originalValue := original.Elem()
  77. // Get the value by calling Elem().
  78. copyValue := reflect.New(originalValue.Type()).Elem()
  79. copyRecursive(originalValue, copyValue)
  80. cpy.Set(copyValue)
  81. case reflect.Struct:
  82. t, ok := original.Interface().(time.Time)
  83. if ok {
  84. cpy.Set(reflect.ValueOf(t))
  85. return
  86. }
  87. // Go through each field of the struct and copy it.
  88. for i := 0; i < original.NumField(); i++ {
  89. // The Type's StructField for a given field is checked to see if StructField.PkgPath
  90. // is set to determine if the field is exported or not because CanSet() returns false
  91. // for settable fields. I'm not sure why. -mohae
  92. if original.Type().Field(i).PkgPath != "" {
  93. continue
  94. }
  95. copyRecursive(original.Field(i), cpy.Field(i))
  96. }
  97. case reflect.Slice:
  98. if original.IsNil() {
  99. return
  100. }
  101. // Make a new slice and copy each element.
  102. cpy.Set(reflect.MakeSlice(original.Type(), original.Len(), original.Cap()))
  103. for i := 0; i < original.Len(); i++ {
  104. copyRecursive(original.Index(i), cpy.Index(i))
  105. }
  106. case reflect.Map:
  107. if original.IsNil() {
  108. return
  109. }
  110. cpy.Set(reflect.MakeMap(original.Type()))
  111. for _, key := range original.MapKeys() {
  112. originalValue := original.MapIndex(key)
  113. copyValue := reflect.New(originalValue.Type()).Elem()
  114. copyRecursive(originalValue, copyValue)
  115. copyKey := Copy(key.Interface())
  116. cpy.SetMapIndex(reflect.ValueOf(copyKey), copyValue)
  117. }
  118. default:
  119. cpy.Set(original)
  120. }
  121. }