reflect.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. package reflect
  2. import (
  3. "fmt"
  4. "reflect"
  5. "strconv"
  6. "strings"
  7. )
  8. func findField(v reflect.Value, field string) reflect.Value {
  9. var (
  10. pos int
  11. tagValue string
  12. refValue reflect.Value
  13. refType reflect.Type
  14. fieldType reflect.StructField
  15. allowTags = []string{"json", "yaml", "xml"}
  16. )
  17. refValue = v.FieldByName(field)
  18. if !refValue.IsValid() {
  19. refType = v.Type()
  20. for i := 0; i < refType.NumField(); i++ {
  21. fieldType = refType.Field(i)
  22. for _, tagName := range allowTags {
  23. tagValue = fieldType.Tag.Get(tagName)
  24. if tagValue == "" {
  25. continue
  26. }
  27. if pos = strings.Index(tagValue, ","); pos != -1 {
  28. tagValue = tagValue[:pos]
  29. }
  30. if tagValue == field {
  31. return v.Field(i)
  32. }
  33. }
  34. }
  35. }
  36. return refValue
  37. }
  38. func safeAssignment(variable reflect.Value, value interface{}) (err error) {
  39. var (
  40. n int64
  41. un uint64
  42. fn float64
  43. kind reflect.Kind
  44. )
  45. rv := reflect.ValueOf(value)
  46. kind = variable.Kind()
  47. if kind != reflect.Slice && kind != reflect.Array && kind != reflect.Map && kind == rv.Kind() {
  48. variable.Set(rv)
  49. return
  50. }
  51. switch kind {
  52. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  53. switch rv.Kind() {
  54. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  55. variable.SetInt(rv.Int())
  56. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  57. variable.SetInt(int64(rv.Uint()))
  58. case reflect.Float32, reflect.Float64:
  59. variable.SetInt(int64(rv.Float()))
  60. case reflect.String:
  61. if n, err = strconv.ParseInt(rv.String(), 10, 64); err == nil {
  62. variable.SetInt(n)
  63. }
  64. default:
  65. err = fmt.Errorf("unsupported kind %s", rv.Kind())
  66. }
  67. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  68. switch rv.Kind() {
  69. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  70. variable.SetUint(uint64(rv.Int()))
  71. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  72. variable.SetUint(rv.Uint())
  73. case reflect.Float32, reflect.Float64:
  74. variable.SetUint(uint64(rv.Float()))
  75. case reflect.String:
  76. if un, err = strconv.ParseUint(rv.String(), 10, 64); err == nil {
  77. variable.SetUint(un)
  78. }
  79. default:
  80. err = fmt.Errorf("unsupported kind %s", rv.Kind())
  81. }
  82. case reflect.Float32, reflect.Float64:
  83. switch rv.Kind() {
  84. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  85. variable.SetFloat(float64(rv.Int()))
  86. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  87. variable.SetFloat(float64(rv.Uint()))
  88. case reflect.Float32, reflect.Float64:
  89. variable.SetFloat(rv.Float())
  90. case reflect.String:
  91. if fn, err = strconv.ParseFloat(rv.String(), 64); err == nil {
  92. variable.SetFloat(fn)
  93. }
  94. default:
  95. err = fmt.Errorf("unsupported kind %s", rv.Kind())
  96. }
  97. case reflect.String:
  98. switch rv.Kind() {
  99. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  100. variable.SetString(strconv.FormatInt(rv.Int(), 10))
  101. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  102. variable.SetString(strconv.FormatUint(rv.Uint(), 10))
  103. case reflect.Float32, reflect.Float64:
  104. variable.SetString(strconv.FormatFloat(rv.Float(), 'f', -1, 64))
  105. case reflect.String:
  106. variable.SetString(rv.String())
  107. default:
  108. variable.SetString(fmt.Sprint(value))
  109. }
  110. default:
  111. err = fmt.Errorf("unsupported kind %s", kind)
  112. }
  113. return
  114. }
  115. func Set(hacky interface{}, field string, value interface{}) (err error) {
  116. var (
  117. n int
  118. refField reflect.Value
  119. )
  120. refVal := reflect.ValueOf(hacky)
  121. if refVal.Kind() == reflect.Ptr {
  122. refVal = reflect.Indirect(refVal)
  123. }
  124. if refVal.Kind() != reflect.Struct {
  125. return fmt.Errorf("%s kind is %v", refVal.Type().String(), refField.Kind())
  126. }
  127. refField = findField(refVal, field)
  128. if !refField.IsValid() {
  129. return fmt.Errorf("%s field `%s` not found", refVal.Type(), field)
  130. }
  131. rv := reflect.ValueOf(value)
  132. fieldKind := refField.Kind()
  133. if fieldKind != reflect.Slice && fieldKind != reflect.Array && fieldKind != reflect.Map && fieldKind == rv.Kind() {
  134. refField.Set(rv)
  135. return
  136. }
  137. switch fieldKind {
  138. case reflect.Array, reflect.Slice:
  139. innerType := refField.Type().Elem()
  140. if rv.Kind() == reflect.Array || rv.Kind() == reflect.Slice {
  141. sliceVar := reflect.MakeSlice(refField.Type(), rv.Len(), rv.Len())
  142. n = 0
  143. for i := 0; i < rv.Len(); i++ {
  144. srcVal := rv.Index(i)
  145. dstVal := reflect.New(innerType).Elem()
  146. if err = safeAssignment(dstVal, srcVal); err == nil {
  147. sliceVar.Index(n).Set(dstVal)
  148. n++
  149. }
  150. }
  151. refField.Set(sliceVar.Slice(0, n))
  152. }
  153. default:
  154. err = safeAssignment(refField, value)
  155. }
  156. return
  157. }