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 }