reflect.go 4.6 KB

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