常用类型及数据操作方法
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

149 lines
4.4 KiB

  1. package helper
  2. import (
  3. "errors"
  4. "fmt"
  5. "reflect"
  6. )
  7. // 结构体泛型提取关键数据
  8. // desk结构体, input提取数据源, columnKey提取的字段,indexKey提取的下标
  9. func StructColumn(desk, input interface{}, columnKey, indexKey string) (err error) {
  10. deskValue := reflect.ValueOf(desk)
  11. if deskValue.Kind() != reflect.Ptr {
  12. return errors.New("desk must be ptr")
  13. }
  14. rv := reflect.ValueOf(input)
  15. if rv.Kind() != reflect.Slice && rv.Kind() != reflect.Array {
  16. return errors.New("input must be map slice or array")
  17. }
  18. rt := reflect.TypeOf(input)
  19. if rt.Elem().Kind() != reflect.Struct {
  20. return errors.New("input's elem must be struct")
  21. }
  22. if len(indexKey) > 0 {
  23. return structIndexColumn(desk, input, columnKey, indexKey)
  24. }
  25. return structColumn(desk, input, columnKey)
  26. }
  27. func structColumn(desk, input interface{}, columnKey string) (err error) {
  28. if len(columnKey) == 0 {
  29. return errors.New("columnKey cannot not be empty")
  30. }
  31. deskElemType := reflect.TypeOf(desk).Elem()
  32. if deskElemType.Kind() != reflect.Slice {
  33. return errors.New("desk must be slice")
  34. }
  35. rv := reflect.ValueOf(input)
  36. rt := reflect.TypeOf(input)
  37. var columnVal reflect.Value
  38. deskValue := reflect.ValueOf(desk)
  39. direct := reflect.Indirect(deskValue)
  40. for i := 0; i < rv.Len(); i++ {
  41. columnVal, err = findStructValByColumnKey(rv.Index(i), rt.Elem(), columnKey)
  42. if err != nil {
  43. return
  44. }
  45. if deskElemType.Elem().Kind() != columnVal.Kind() {
  46. return errors.New(fmt.Sprintf("your slice must be []%s", columnVal.Kind()))
  47. }
  48. direct.Set(reflect.Append(direct, columnVal))
  49. }
  50. return
  51. }
  52. func findStructValByColumnKey(curVal reflect.Value, elemType reflect.Type, columnKey string) (columnVal reflect.Value, err error) {
  53. columnExist := false
  54. for i := 0; i < elemType.NumField(); i++ {
  55. curField := curVal.Field(i)
  56. if elemType.Field(i).Name == columnKey {
  57. columnExist = true
  58. columnVal = curField
  59. continue
  60. }
  61. }
  62. if !columnExist {
  63. return columnVal, errors.New(fmt.Sprintf("columnKey %s not found in %s's field", columnKey, elemType))
  64. }
  65. return
  66. }
  67. func structIndexColumn(desk, input interface{}, columnKey, indexKey string) (err error) {
  68. deskValue := reflect.ValueOf(desk)
  69. if deskValue.Elem().Kind() != reflect.Map {
  70. return errors.New("desk must be map")
  71. }
  72. deskElem := deskValue.Type().Elem()
  73. if len(columnKey) == 0 && deskElem.Elem().Kind() != reflect.Struct {
  74. return errors.New(fmt.Sprintf("desk's elem expect struct, got %s", deskElem.Elem().Kind()))
  75. }
  76. rv := reflect.ValueOf(input)
  77. rt := reflect.TypeOf(input)
  78. elemType := rt.Elem()
  79. var indexVal, columnVal reflect.Value
  80. direct := reflect.Indirect(deskValue)
  81. mapReflect := reflect.MakeMap(deskElem)
  82. deskKey := deskValue.Type().Elem().Key()
  83. for i := 0; i < rv.Len(); i++ {
  84. curVal := rv.Index(i)
  85. indexVal, columnVal, err = findStructValByIndexKey(curVal, elemType, indexKey, columnKey)
  86. if err != nil {
  87. return
  88. }
  89. if deskKey.Kind() != indexVal.Kind() {
  90. return errors.New(fmt.Sprintf("cant't convert %s to %s, your map'key must be %s", indexVal.Kind(), deskKey.Kind(), indexVal.Kind()))
  91. }
  92. if len(columnKey) == 0 {
  93. mapReflect.SetMapIndex(indexVal, curVal)
  94. direct.Set(mapReflect)
  95. } else {
  96. if deskElem.Elem().Kind() != columnVal.Kind() {
  97. return errors.New(fmt.Sprintf("your map must be map[%s]%s", indexVal.Kind(), columnVal.Kind()))
  98. }
  99. mapReflect.SetMapIndex(indexVal, columnVal)
  100. direct.Set(mapReflect)
  101. }
  102. }
  103. return
  104. }
  105. func findStructValByIndexKey(curVal reflect.Value, elemType reflect.Type, indexKey, columnKey string) (indexVal, columnVal reflect.Value, err error) {
  106. indexExist := false
  107. columnExist := false
  108. for i := 0; i < elemType.NumField(); i++ {
  109. curField := curVal.Field(i)
  110. if elemType.Field(i).Name == indexKey {
  111. switch curField.Kind() {
  112. case reflect.String, reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int, reflect.Float64, reflect.Float32:
  113. indexExist = true
  114. indexVal = curField
  115. default:
  116. return indexVal, columnVal, errors.New("indexKey must be int float or string")
  117. }
  118. }
  119. if elemType.Field(i).Name == columnKey {
  120. columnExist = true
  121. columnVal = curField
  122. continue
  123. }
  124. }
  125. if !indexExist {
  126. return indexVal, columnVal, errors.New(fmt.Sprintf("indexKey %s not found in %s's field", indexKey, elemType))
  127. }
  128. if len(columnKey) > 0 && !columnExist {
  129. return indexVal, columnVal, errors.New(fmt.Sprintf("columnKey %s not found in %s's field", columnKey, elemType))
  130. }
  131. return
  132. }