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  }