github.com/sohaha/zlsgo@v1.7.13-0.20240501141223-10dd1a906f76/zutil/reflect.go (about) 1 package zutil 2 3 import ( 4 "errors" 5 "reflect" 6 "strconv" 7 8 "github.com/sohaha/zlsgo/zreflect" 9 "github.com/sohaha/zlsgo/ztype" 10 ) 11 12 func SetValue(vTypeOf reflect.Kind, vValueOf reflect.Value, value interface{}) (err error) { 13 typeErr := errors.New(vTypeOf.String() + " type assignment is not supported") 14 vString := "" 15 v, ok := value.(string) 16 if ok { 17 vString = v 18 } else { 19 vString = ztype.ToString(value) 20 } 21 switch vTypeOf { 22 case reflect.String: 23 vValueOf.SetString(vString) 24 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 25 var v int64 26 v, err = strconv.ParseInt(vString, 10, 64) 27 if err != nil { 28 err = errors.New("must be an integer") 29 } else if vValueOf.OverflowInt(v) { 30 err = typeErr 31 } 32 vValueOf.SetInt(v) 33 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 34 var v uint64 35 v, err = strconv.ParseUint(vString, 10, 64) 36 if err != nil { 37 err = errors.New("must be an unsigned integer") 38 } else if vValueOf.OverflowUint(v) { 39 err = typeErr 40 } 41 vValueOf.SetUint(v) 42 case reflect.Float32, reflect.Float64: 43 var v float64 44 v, err = strconv.ParseFloat(vString, 64) 45 if err != nil { 46 err = errors.New("must be decimal") 47 } else if vValueOf.OverflowFloat(v) { 48 err = typeErr 49 } 50 case reflect.Bool: 51 var v bool 52 v, err = strconv.ParseBool(vString) 53 if err != nil { 54 err = errors.New("must be boolean") 55 } 56 vValueOf.SetBool(v) 57 case reflect.Slice: 58 if value != nil { 59 vValueOf.Set(zreflect.ValueOf(value)) 60 } else { 61 err = errors.New("must be slice") 62 } 63 case reflect.Struct: 64 err = setStruct(vValueOf, value) 65 default: 66 err = typeErr 67 } 68 69 return err 70 } 71 72 // setStruct todo unfinished 73 func setStruct(v reflect.Value, value interface{}) (err error) { 74 valueTypeof := reflect.TypeOf(value) 75 kind := valueTypeof.Kind() 76 if kind != reflect.Map { 77 err = errors.New("must be map[]") 78 return 79 } 80 81 if values, ok := value.(map[string]string); ok { 82 err = ReflectForNumField(v, func(fieldName, fieldTag string, kind reflect.Kind, 83 field reflect.Value) error { 84 if v, ok := values[fieldTag]; ok { 85 return SetValue(kind, field, v) 86 } 87 return nil 88 }) 89 } else { 90 err = errors.New("not supported") 91 } 92 93 return 94 } 95 96 func ReflectStructField(v reflect.Type, fn func( 97 numField int, fieldTag string, field reflect.StructField) error, tag ...string) error { 98 var err error 99 tagKey := "z" 100 if len(tag) > 0 { 101 tagKey = tag[0] 102 } 103 if v.Kind() == reflect.Ptr { 104 v = v.Elem() 105 } 106 for i := 0; i < v.NumField(); i++ { 107 field := v.Field(i) 108 fieldTag := "" 109 if tagKey != "" { 110 fieldTag = field.Tag.Get(tagKey) 111 } 112 if fieldTag == "-" { 113 continue 114 } 115 fieldName := field.Name 116 if fieldTag == "" { 117 fieldTag = fieldName 118 } 119 err = fn(i, fieldTag, field) 120 if err != nil { 121 return err 122 } 123 } 124 return nil 125 } 126 127 func ReflectForNumField(v reflect.Value, fn func(fieldName, fieldTag string, 128 kind reflect.Kind, field reflect.Value) error, tag ...string) error { 129 var err error 130 tagKey := zreflect.Tag 131 if len(tag) > 0 { 132 tagKey = tag[0] 133 } 134 for i := 0; i < v.NumField(); i++ { 135 field := v.Field(i) 136 tfield := v.Type().Field(i) 137 fieldTag := "" 138 if tagKey != "" { 139 fieldTag = tfield.Tag.Get(tagKey) 140 } 141 if fieldTag == "-" || !field.CanSet() { 142 continue 143 } 144 fieldName := tfield.Name 145 fieldType := field.Type() 146 kind := fieldType.Kind() 147 if fieldTag == "" { 148 fieldTag = fieldName 149 } 150 if kind == reflect.Struct { // && tfield.Anonymous 151 if err = ReflectForNumField(field, fn, tag...); err != nil { 152 return err 153 } 154 } 155 if err = fn(fieldName, fieldTag, kind, field); err != nil { 156 return err 157 } 158 } 159 return err 160 } 161 162 // GetAllMethod get all methods of struct 163 func GetAllMethod(s interface{}, fn func(numMethod int, m reflect.Method) error) error { 164 typ := zreflect.ValueOf(s) 165 if fn == nil { 166 return nil 167 } 168 return zreflect.ForEachMethod(typ, func(index int, method reflect.Method, value reflect.Value) error { 169 return fn(index, method) 170 }) 171 } 172 173 // RunAllMethod run all methods of struct 174 func RunAllMethod(st interface{}, args ...interface{}) (err error) { 175 return RunAssignMethod(st, func(methodName string) bool { 176 return true 177 }, args...) 178 } 179 180 // RunAssignMethod run assign methods of struct 181 func RunAssignMethod(st interface{}, filter func(methodName string) bool, args ...interface{}) (err error) { 182 valueOf := zreflect.ValueOf(st) 183 err = GetAllMethod(st, func(numMethod int, m reflect.Method) error { 184 if !filter(m.Name) { 185 return nil 186 } 187 var values []reflect.Value 188 for _, v := range args { 189 values = append(values, zreflect.ValueOf(v)) 190 } 191 192 return TryCatch(func() error { 193 valueOf.Method(numMethod).Call(values) 194 return nil 195 }) 196 }) 197 198 return 199 }