gitee.com/quant1x/gox@v1.21.2/api/reflect_array.go (about)

     1  package api
     2  
     3  import (
     4  	"errors"
     5  	"reflect"
     6  	"strconv"
     7  	"sync"
     8  )
     9  
    10  var (
    11  	ErrNotConvert = errors.New("can not Convert")
    12  )
    13  
    14  var (
    15  	__tagArrayMutex sync.RWMutex
    16  	// 结构体 tag array的反射的字段缓存
    17  	__mapTagArray = map[reflect.Type]map[int]reflect.StructField{}
    18  )
    19  
    20  func initTag(t reflect.Type) map[int]reflect.StructField {
    21  	__tagArrayMutex.RLock()
    22  	ma, mok := __mapTagArray[t]
    23  	__tagArrayMutex.RUnlock()
    24  	if mok {
    25  		return ma
    26  	}
    27  	ma = nil
    28  	fieldNum := t.NumField()
    29  	for i := 0; i < fieldNum; i++ {
    30  		field := t.Field(i)
    31  		tag := field.Tag
    32  		if len(tag) > 0 {
    33  			tv, ok := tag.Lookup("array")
    34  			if ok {
    35  				index, err := strconv.Atoi(tv)
    36  				if err == nil {
    37  					if ma == nil {
    38  						ma = make(map[int]reflect.StructField)
    39  						__mapTagArray[t] = ma
    40  					}
    41  					__tagArrayMutex.Lock()
    42  					ma[index] = field
    43  					__tagArrayMutex.Unlock()
    44  
    45  				}
    46  			}
    47  		}
    48  	}
    49  	return ma
    50  }
    51  
    52  // Convert 将字符串数组按照下标的序号反射给一个结构体
    53  func Convert[T any](data []string, v *T) error {
    54  	obj := reflect.ValueOf(v)
    55  	t := obj.Type()
    56  	if obj.Kind() == reflect.Ptr {
    57  		t = t.Elem()
    58  		obj = obj.Elem()
    59  	}
    60  	ma := initTag(t)
    61  	if ma == nil {
    62  		return ErrNotConvert
    63  	}
    64  	//fieldNum := t.NumField()
    65  	fieldNum := len(data)
    66  	for i := 0; i < fieldNum; i++ {
    67  		field, ok := ma[i]
    68  		if ok {
    69  			dv := data[i]
    70  			ov := obj.FieldByName(field.Name)
    71  			if ov.CanSet() {
    72  				var value interface{}
    73  				switch ov.Interface().(type) {
    74  				case string:
    75  					value = dv
    76  				case int8:
    77  					t := ParseInt(dv)
    78  					value = int8(t)
    79  				case int16:
    80  					t := ParseInt(dv)
    81  					value = int16(t)
    82  				case int32:
    83  					t := ParseInt(dv)
    84  					value = int32(t)
    85  				case int64:
    86  					t := ParseInt(dv)
    87  					value = int64(t)
    88  				case uint8:
    89  					t := ParseUint(dv)
    90  					value = uint8(t)
    91  				case uint16:
    92  					t := ParseUint(dv)
    93  					value = uint16(t)
    94  				case uint32:
    95  					t := ParseUint(dv)
    96  					value = uint32(t)
    97  				case uint64:
    98  					t := ParseUint(dv)
    99  					value = t
   100  				case float32:
   101  					t := ParseFloat(dv)
   102  					value = float32(t)
   103  				case float64:
   104  					t := ParseFloat(dv)
   105  					value = t
   106  				case bool:
   107  					t, _ := strconv.ParseBool(dv)
   108  					value = t
   109  				default:
   110  					value = dv
   111  				}
   112  				ov.Set(reflect.ValueOf(value))
   113  			}
   114  		}
   115  	}
   116  	return nil
   117  }