gutil_struct.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // Copyright GoFrame 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 gutil
  7. import (
  8. "reflect"
  9. "github.com/gogf/gf/v2/errors/gcode"
  10. "github.com/gogf/gf/v2/errors/gerror"
  11. "github.com/gogf/gf/v2/os/gstructs"
  12. "github.com/gogf/gf/v2/util/gconv"
  13. )
  14. // StructToSlice converts struct to slice of which all keys and values are its items.
  15. // Eg: {"K1": "v1", "K2": "v2"} => ["K1", "v1", "K2", "v2"]
  16. func StructToSlice(data interface{}) []interface{} {
  17. var (
  18. reflectValue = reflect.ValueOf(data)
  19. reflectKind = reflectValue.Kind()
  20. )
  21. for reflectKind == reflect.Ptr {
  22. reflectValue = reflectValue.Elem()
  23. reflectKind = reflectValue.Kind()
  24. }
  25. switch reflectKind {
  26. case reflect.Struct:
  27. array := make([]interface{}, 0)
  28. // Note that, it uses the gconv tag name instead of the attribute name if
  29. // the gconv tag is fined in the struct attributes.
  30. for k, v := range gconv.Map(reflectValue) {
  31. array = append(array, k)
  32. array = append(array, v)
  33. }
  34. return array
  35. }
  36. return nil
  37. }
  38. // FillStructWithDefault fills attributes of pointed struct with tag value from `default/d` tag .
  39. // The parameter `structPtr` should be either type of *struct/[]*struct.
  40. func FillStructWithDefault(structPtr interface{}) error {
  41. var (
  42. reflectValue reflect.Value
  43. )
  44. if rv, ok := structPtr.(reflect.Value); ok {
  45. reflectValue = rv
  46. } else {
  47. reflectValue = reflect.ValueOf(structPtr)
  48. }
  49. switch reflectValue.Kind() {
  50. case reflect.Ptr:
  51. // Nothing to do.
  52. case reflect.Array, reflect.Slice:
  53. if reflectValue.Elem().Kind() != reflect.Ptr {
  54. return gerror.NewCodef(
  55. gcode.CodeInvalidParameter,
  56. `invalid parameter "%s", the element of slice should be type of pointer of struct, but given "%s"`,
  57. reflectValue.Type().String(), reflectValue.Elem().Type().String(),
  58. )
  59. }
  60. default:
  61. return gerror.NewCodef(
  62. gcode.CodeInvalidParameter,
  63. `invalid parameter "%s", should be type of pointer of struct`,
  64. reflectValue.Type().String(),
  65. )
  66. }
  67. if reflectValue.IsNil() {
  68. return gerror.NewCode(
  69. gcode.CodeInvalidParameter,
  70. `the pointed struct object should not be nil`,
  71. )
  72. }
  73. if !reflectValue.Elem().IsValid() {
  74. return gerror.NewCode(
  75. gcode.CodeInvalidParameter,
  76. `the pointed struct object should be valid`,
  77. )
  78. }
  79. fields, err := gstructs.Fields(gstructs.FieldsInput{
  80. Pointer: reflectValue,
  81. RecursiveOption: gstructs.RecursiveOptionNone,
  82. })
  83. if err != nil {
  84. return err
  85. }
  86. for _, field := range fields {
  87. if defaultValue := field.TagDefault(); defaultValue != "" {
  88. if field.IsEmpty() {
  89. field.Value.Set(reflect.ValueOf(
  90. gconv.ConvertWithRefer(defaultValue, field.Value),
  91. ))
  92. }
  93. }
  94. }
  95. return nil
  96. }