github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/sqx/struct.go (about)

     1  package sqx
     2  
     3  import "reflect"
     4  
     5  // StructField represents the information of a struct's field.
     6  type StructField struct {
     7  	Parent      *StructValue
     8  	Field       reflect.Value
     9  	Index       int
    10  	StructField reflect.StructField
    11  	Type        reflect.Type
    12  	Name        string
    13  	Tag         reflect.StructTag
    14  	Kind        reflect.Kind
    15  	PkgPath     string
    16  }
    17  
    18  // GetTag returns the value associated with key in the tag string.
    19  // If there is no such key in the tag, Get returns the empty string.
    20  func (f StructField) GetTag(name string) string {
    21  	if v, ok := f.Tag.Lookup(name); ok {
    22  		return v
    23  	}
    24  
    25  	return ""
    26  }
    27  
    28  // GetTagOr returns the tag's value of the field or defaultValue when tag is empty.
    29  func (f StructField) GetTagOr(tagName string, defaultValue string) string {
    30  	tag := f.GetTag(tagName)
    31  	if tag != "" {
    32  		return tag
    33  	}
    34  
    35  	return defaultValue
    36  }
    37  
    38  // StructValue represents the structure for a struct.
    39  type StructValue struct {
    40  	StructSelf reflect.Value
    41  	NumField   int
    42  	FieldTypes []reflect.StructField
    43  }
    44  
    45  // MakeStructValue makes a StructValue by a struct's value.
    46  func MakeStructValue(structSelf reflect.Value) *StructValue {
    47  	sv := &StructValue{StructSelf: structSelf, NumField: structSelf.NumField()}
    48  
    49  	sv.FieldTypes = make([]reflect.StructField, sv.NumField)
    50  	for i := 0; i < sv.NumField; i++ {
    51  		sv.FieldTypes[i] = sv.StructSelf.Type().Field(i)
    52  	}
    53  
    54  	return sv
    55  }
    56  
    57  // FieldIndexByName return's the index of field by its name.
    58  // If the field is not found, FieldIndexByName returns -1.
    59  func (s *StructValue) FieldIndexByName(name string) int {
    60  	for i, ft := range s.FieldTypes {
    61  		if ft.Name == name {
    62  			return i
    63  		}
    64  	}
    65  
    66  	return -1
    67  }
    68  
    69  // FieldByName returns the StructField which has the name.
    70  func (s *StructValue) FieldByName(name string) (StructField, bool) {
    71  	index := s.FieldIndexByName(name)
    72  	if index < 0 {
    73  		return StructField{}, false
    74  	}
    75  
    76  	return s.FieldByIndex(index), true
    77  }
    78  
    79  // FieldByIndex return the StructField at index.
    80  func (s *StructValue) FieldByIndex(index int) StructField {
    81  	fieldType := s.FieldTypes[index]
    82  	field := s.StructSelf.Field(index)
    83  
    84  	return StructField{
    85  		Parent:      s,
    86  		Field:       field,
    87  		Index:       index,
    88  		StructField: fieldType,
    89  		Type:        fieldType.Type,
    90  		Name:        fieldType.Name,
    91  		Tag:         fieldType.Tag,
    92  		Kind:        field.Kind(),
    93  		PkgPath:     fieldType.PkgPath,
    94  	}
    95  }