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