github.com/seeker-insurance/kit@v0.0.13/flect/flect.go (about) 1 //Package flect is meant to work alongside go's `reflect` library, containing additional runtime reflection tools 2 package flect 3 4 import ( 5 "reflect" 6 "strings" 7 8 "github.com/seeker-insurance/kit/functools" 9 ) 10 11 type tagOpts []string 12 13 type groupConfig int 14 const ( 15 WithZeros groupConfig = iota 16 WithoutZeros 17 ) 18 19 func (opts tagOpts) HasOption(name string) bool { 20 return functools.StringSliceContains(opts, name) 21 } 22 23 func TagValues(t reflect.StructTag, name string) (value string, opts tagOpts, ok bool) { 24 fullValue, ok := t.Lookup(name) 25 if !ok { 26 return 27 } 28 splitValue := strings.Split(fullValue, ",") 29 if len(splitValue) > 0 { 30 opts = tagOpts(splitValue[1:]) 31 } 32 return splitValue[0], opts, true 33 } 34 35 func Values(structs ...interface{}) []reflect.Value { 36 values := make([]reflect.Value, len(structs)) 37 for i, s := range structs { 38 values[i] = reflect.ValueOf(s) 39 } 40 return values 41 } 42 43 func Fields(val reflect.Value) []reflect.StructField { 44 fields := make([]reflect.StructField, val.NumField()) 45 for i := range fields { 46 fields[i] = val.Type().Field(i) 47 } 48 return fields 49 } 50 51 func ValuesByTag(tag string, config groupConfig, structs ...interface{}) map[string]interface{} { 52 tagValues := make(map[string]interface{}) 53 for _, data := range structs { 54 for _, val := range Values(data) { 55 for j, field := range Fields(val) { 56 tagValue, _, ok := TagValues(field.Tag, "attr") 57 if ok { 58 attrValue := val.Field(j).Interface() 59 if config == WithoutZeros && IsZeroOfType(attrValue) { 60 continue 61 } 62 tagValues[tagValue] = attrValue 63 } 64 } 65 } 66 } 67 return tagValues 68 } 69 70 func IsZeroOfType(x interface{}) bool { 71 return reflect.DeepEqual(x, reflect.Zero(reflect.TypeOf(x)).Interface()) 72 }