coppier.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. package coppier
  2. /*
  3. * source https://github.com/jinzhu/copier.git
  4. */
  5. import (
  6. "database/sql"
  7. "errors"
  8. "reflect"
  9. )
  10. // Copy copy things
  11. func Copy(toValue interface{}, fromValue interface{}) (err error) {
  12. var (
  13. isSlice bool
  14. amount = 1
  15. from = indirect(reflect.ValueOf(fromValue))
  16. to = indirect(reflect.ValueOf(toValue))
  17. )
  18. if !to.CanAddr() {
  19. return errors.New("copy to value is unaddressable")
  20. }
  21. // Return is from value is invalid
  22. if !from.IsValid() {
  23. return
  24. }
  25. fromType := indirectType(from.Type())
  26. toType := indirectType(to.Type())
  27. // Just set it if possible to assign
  28. // And need to do copy anyway if the type is struct
  29. if fromType.Kind() != reflect.Struct && from.Type().AssignableTo(to.Type()) {
  30. to.Set(from)
  31. return
  32. }
  33. if fromType.Kind() != reflect.Struct || toType.Kind() != reflect.Struct {
  34. return
  35. }
  36. if to.Kind() == reflect.Slice {
  37. isSlice = true
  38. if from.Kind() == reflect.Slice {
  39. amount = from.Len()
  40. }
  41. }
  42. for i := 0; i < amount; i++ {
  43. var dest, source reflect.Value
  44. if isSlice {
  45. // source
  46. if from.Kind() == reflect.Slice {
  47. source = indirect(from.Index(i))
  48. } else {
  49. source = indirect(from)
  50. }
  51. // dest
  52. dest = indirect(reflect.New(toType).Elem())
  53. } else {
  54. source = indirect(from)
  55. dest = indirect(to)
  56. }
  57. // check source
  58. if source.IsValid() {
  59. fromTypeFields := deepFields(fromType)
  60. //fmt.Printf("%#v", fromTypeFields)
  61. // Copy from field to field or method
  62. for _, field := range fromTypeFields {
  63. name := field.Name
  64. if fromField := source.FieldByName(name); fromField.IsValid() {
  65. // has field
  66. if toField := dest.FieldByName(name); toField.IsValid() {
  67. if toField.CanSet() {
  68. if !set(toField, fromField) {
  69. if err := Copy(toField.Addr().Interface(), fromField.Interface()); err != nil {
  70. return err
  71. }
  72. }
  73. }
  74. } else {
  75. // try to set to method
  76. var toMethod reflect.Value
  77. if dest.CanAddr() {
  78. toMethod = dest.Addr().MethodByName(name)
  79. } else {
  80. toMethod = dest.MethodByName(name)
  81. }
  82. if toMethod.IsValid() && toMethod.Type().NumIn() == 1 && fromField.Type().AssignableTo(toMethod.Type().In(0)) {
  83. toMethod.Call([]reflect.Value{fromField})
  84. }
  85. }
  86. }
  87. }
  88. // Copy from method to field
  89. for _, field := range deepFields(toType) {
  90. name := field.Name
  91. var fromMethod reflect.Value
  92. if source.CanAddr() {
  93. fromMethod = source.Addr().MethodByName(name)
  94. } else {
  95. fromMethod = source.MethodByName(name)
  96. }
  97. if fromMethod.IsValid() && fromMethod.Type().NumIn() == 0 && fromMethod.Type().NumOut() == 1 {
  98. if toField := dest.FieldByName(name); toField.IsValid() && toField.CanSet() {
  99. values := fromMethod.Call([]reflect.Value{})
  100. if len(values) >= 1 {
  101. set(toField, values[0])
  102. }
  103. }
  104. }
  105. }
  106. }
  107. if isSlice {
  108. if dest.Addr().Type().AssignableTo(to.Type().Elem()) {
  109. to.Set(reflect.Append(to, dest.Addr()))
  110. } else if dest.Type().AssignableTo(to.Type().Elem()) {
  111. to.Set(reflect.Append(to, dest))
  112. }
  113. }
  114. }
  115. return
  116. }
  117. func deepFields(reflectType reflect.Type) []reflect.StructField {
  118. var fields []reflect.StructField
  119. if reflectType = indirectType(reflectType); reflectType.Kind() == reflect.Struct {
  120. for i := 0; i < reflectType.NumField(); i++ {
  121. v := reflectType.Field(i)
  122. if v.Anonymous {
  123. fields = append(fields, deepFields(v.Type)...)
  124. } else {
  125. fields = append(fields, v)
  126. }
  127. }
  128. }
  129. return fields
  130. }
  131. func indirect(reflectValue reflect.Value) reflect.Value {
  132. for reflectValue.Kind() == reflect.Ptr {
  133. reflectValue = reflectValue.Elem()
  134. }
  135. return reflectValue
  136. }
  137. func indirectType(reflectType reflect.Type) reflect.Type {
  138. for reflectType.Kind() == reflect.Ptr || reflectType.Kind() == reflect.Slice {
  139. reflectType = reflectType.Elem()
  140. }
  141. return reflectType
  142. }
  143. func set(to, from reflect.Value) bool {
  144. if from.IsValid() {
  145. if to.Kind() == reflect.Ptr {
  146. //set `to` to nil if from is nil
  147. if from.Kind() == reflect.Ptr && from.IsNil() {
  148. to.Set(reflect.Zero(to.Type()))
  149. return true
  150. } else if to.IsNil() {
  151. to.Set(reflect.New(to.Type().Elem()))
  152. }
  153. to = to.Elem()
  154. }
  155. if from.Type().ConvertibleTo(to.Type()) {
  156. to.Set(from.Convert(to.Type()))
  157. } else if scanner, ok := to.Addr().Interface().(sql.Scanner); ok {
  158. err := scanner.Scan(from.Interface())
  159. if err != nil {
  160. return false
  161. }
  162. } else if from.Kind() == reflect.Ptr {
  163. return set(to, from.Elem())
  164. } else {
  165. return false
  166. }
  167. }
  168. return true
  169. }