github.com/wfusion/gofusion@v1.1.14/common/utils/tag.go (about) 1 package utils 2 3 import ( 4 "reflect" 5 ) 6 7 type parseTagOption struct { 8 tag string 9 overwrite bool 10 unmarshalType unmarshalType 11 } 12 13 func ParseTagName(tag string) OptionFunc[parseTagOption] { 14 return func(o *parseTagOption) { 15 o.tag = tag 16 } 17 } 18 19 func ParseTagOverwrite(overwrite bool) OptionFunc[parseTagOption] { 20 return func(o *parseTagOption) { 21 o.overwrite = overwrite 22 } 23 } 24 25 func ParseTagUnmarshalType(unmarshalTag unmarshalType) OptionFunc[parseTagOption] { 26 return func(o *parseTagOption) { 27 o.unmarshalType = unmarshalTag 28 } 29 } 30 31 func ParseTag(data any, opts ...OptionExtender) (err error) { 32 opt := ApplyOptions[parseTagOption](opts...) 33 stepInKinds := NewSet(reflect.Struct, reflect.Array, reflect.Slice, reflect.Map) 34 TraverseValue(data, false, func(field reflect.StructField, value reflect.Value) (end, stepIn bool) { 35 if !value.IsValid() || !value.CanSet() || !value.CanAddr() || !value.CanInterface() { 36 return 37 } 38 39 vk := value.Kind() 40 stepIn = stepInKinds.Contains(vk) || 41 (vk == reflect.Ptr && value.Elem().IsValid() && value.Elem().Kind() == reflect.Struct) 42 43 defaultString := field.Tag.Get(opt.tag) 44 if IsStrBlank(defaultString) || (!opt.overwrite && !IsBlank(value)) { 45 return 46 } 47 48 defaultValue := reflect.New(value.Type()).Interface() 49 if err = Unmarshal(defaultString, defaultValue, opt.unmarshalType); err != nil { 50 end = true 51 return 52 } 53 value.Set(reflect.ValueOf(defaultValue).Elem()) 54 return 55 }) 56 57 return 58 }