github.com/easysoft/zendata@v0.0.0-20240513203326-705bd5a7fd67/cmd/test/others/func/proto/defaults/defaults.go (about) 1 package defaults 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "log" 8 "reflect" 9 "strconv" 10 "time" 11 12 "github.com/easysoft/zendata/internal/pkg/model" 13 "github.com/easysoft/zendata/pkg/utils/vari" 14 ) 15 16 var ( 17 errInvalidType = errors.New("not a struct pointer") 18 ) 19 20 const ( 21 fieldName = "default" 22 ) 23 24 // Set initializes members in a struct referenced by a pointer. 25 // Maps and slices are initialized by `make` and other primitive types are set with default values. 26 // `ptr` should be a struct pointer 27 func Set(ptr interface{}, fld *model.DefField) error { 28 if reflect.TypeOf(ptr).Kind() != reflect.Ptr { 29 return errInvalidType 30 } 31 32 v := reflect.ValueOf(ptr).Elem() 33 t := v.Type() 34 35 if t.Kind() != reflect.Struct { 36 return errInvalidType 37 } 38 39 if vari.Verbose { 40 log.Println(fmt.Sprintf("1. struct '%s'", v.String())) 41 } 42 43 if t == nil { 44 log.Println("") 45 } 46 fld.Field = t.Name() 47 fld.Range = "-" 48 49 for i := 0; i < t.NumField(); i++ { 50 childFld := model.DefField{} 51 childFld.Field = t.Field(i).Name 52 childFld.Range = "-" 53 fld.Fields = append(fld.Fields, childFld) 54 55 defaultVal := t.Field(i).Tag.Get(fieldName) 56 if defaultVal != "-" { 57 if err := setField(v.Field(i), defaultVal, &childFld); err != nil { 58 return err 59 } 60 } 61 } 62 callSetter(ptr) 63 return nil 64 } 65 66 // MustSet function is a wrapper of Set function 67 // It will call Set and panic if err not equals nil. 68 func MustSet(ptr interface{}) { 69 if err := Set(ptr, nil); err != nil { 70 panic(err) 71 } 72 } 73 74 func setField(field reflect.Value, defaultVal string, fld *model.DefField) error { 75 if !field.CanSet() { 76 return nil 77 } 78 79 if vari.Verbose { 80 log.Println(fmt.Sprintf("2. set value '%s'", field.String())) 81 } 82 83 //if !shouldInitializeField(field, defaultVal) { 84 // return nil 85 //} 86 87 if isInitialValue(field) { 88 kind := field.Kind() 89 90 switch kind { 91 case reflect.Bool: 92 if val, err := strconv.ParseBool(defaultVal); err == nil { 93 field.Set(reflect.ValueOf(val).Convert(field.Type())) 94 } 95 case reflect.Int: 96 if val, err := strconv.ParseInt(defaultVal, 0, strconv.IntSize); err == nil { 97 field.Set(reflect.ValueOf(int(val)).Convert(field.Type())) 98 } 99 case reflect.Int8: 100 if val, err := strconv.ParseInt(defaultVal, 0, 8); err == nil { 101 field.Set(reflect.ValueOf(int8(val)).Convert(field.Type())) 102 } 103 case reflect.Int16: 104 if val, err := strconv.ParseInt(defaultVal, 0, 16); err == nil { 105 field.Set(reflect.ValueOf(int16(val)).Convert(field.Type())) 106 } 107 case reflect.Int32: 108 if val, err := strconv.ParseInt(defaultVal, 0, 32); err == nil { 109 field.Set(reflect.ValueOf(int32(val)).Convert(field.Type())) 110 } 111 case reflect.Int64: 112 if val, err := time.ParseDuration(defaultVal); err == nil { 113 field.Set(reflect.ValueOf(val).Convert(field.Type())) 114 } else if val, err := strconv.ParseInt(defaultVal, 0, 64); err == nil { 115 field.Set(reflect.ValueOf(val).Convert(field.Type())) 116 } 117 case reflect.Uint: 118 if val, err := strconv.ParseUint(defaultVal, 0, strconv.IntSize); err == nil { 119 field.Set(reflect.ValueOf(uint(val)).Convert(field.Type())) 120 } 121 case reflect.Uint8: 122 if val, err := strconv.ParseUint(defaultVal, 0, 8); err == nil { 123 field.Set(reflect.ValueOf(uint8(val)).Convert(field.Type())) 124 } 125 case reflect.Uint16: 126 if val, err := strconv.ParseUint(defaultVal, 0, 16); err == nil { 127 field.Set(reflect.ValueOf(uint16(val)).Convert(field.Type())) 128 } 129 case reflect.Uint32: 130 if val, err := strconv.ParseUint(defaultVal, 0, 32); err == nil { 131 field.Set(reflect.ValueOf(uint32(val)).Convert(field.Type())) 132 } 133 case reflect.Uint64: 134 if val, err := strconv.ParseUint(defaultVal, 0, 64); err == nil { 135 field.Set(reflect.ValueOf(val).Convert(field.Type())) 136 } 137 case reflect.Uintptr: 138 if val, err := strconv.ParseUint(defaultVal, 0, strconv.IntSize); err == nil { 139 field.Set(reflect.ValueOf(uintptr(val)).Convert(field.Type())) 140 } 141 case reflect.Float32: 142 if val, err := strconv.ParseFloat(defaultVal, 32); err == nil { 143 field.Set(reflect.ValueOf(float32(val)).Convert(field.Type())) 144 } 145 case reflect.Float64: 146 if val, err := strconv.ParseFloat(defaultVal, 64); err == nil { 147 field.Set(reflect.ValueOf(val).Convert(field.Type())) 148 } 149 case reflect.String: 150 field.Set(reflect.ValueOf(defaultVal).Convert(field.Type())) 151 152 case reflect.Slice: 153 ref := reflect.New(field.Type()) 154 ref.Elem().Set(reflect.MakeSlice(field.Type(), 0, 0)) 155 if defaultVal != "" && defaultVal != "[]" { 156 if err := json.Unmarshal([]byte(defaultVal), ref.Interface()); err != nil { 157 return err 158 } 159 } 160 field.Set(ref.Elem().Convert(field.Type())) 161 case reflect.Map: 162 ref := reflect.New(field.Type()) 163 ref.Elem().Set(reflect.MakeMap(field.Type())) 164 if defaultVal != "" && defaultVal != "{}" { 165 if err := json.Unmarshal([]byte(defaultVal), ref.Interface()); err != nil { 166 return err 167 } 168 } 169 field.Set(ref.Elem().Convert(field.Type())) 170 case reflect.Struct: 171 if defaultVal != "" && defaultVal != "{}" { 172 if err := json.Unmarshal([]byte(defaultVal), field.Addr().Interface()); err != nil { 173 return err 174 } 175 } 176 case reflect.Ptr: 177 v := reflect.New(field.Type().Elem()) 178 field.Set(v) 179 } 180 } 181 182 switch field.Kind() { 183 case reflect.Ptr: 184 setField(field.Elem(), defaultVal, fld) 185 callSetter(field.Interface()) 186 case reflect.Struct: 187 if err := Set(field.Addr().Interface(), fld); err != nil { 188 return err 189 } 190 case reflect.Slice: 191 for j := 0; j < field.Len(); j++ { 192 if err := setField(field.Index(j), defaultVal, &model.DefField{}); err != nil { 193 return err 194 } 195 } 196 } 197 198 return nil 199 } 200 201 func isInitialValue(field reflect.Value) bool { 202 return reflect.DeepEqual(reflect.Zero(field.Type()).Interface(), field.Interface()) 203 } 204 205 func shouldInitializeField(field reflect.Value, tag string) bool { 206 kind := field.Kind() 207 208 switch kind { 209 case reflect.Struct: 210 return true 211 case reflect.Ptr: 212 if !field.IsNil() && field.Elem().Kind() == reflect.Struct { 213 return true 214 } 215 case reflect.Slice: 216 return field.Len() > 0 || tag != "" 217 } 218 219 return tag != "" 220 } 221 222 // CanUpdate returns true when the given value is an initial value of its type 223 func CanUpdate(v interface{}) bool { 224 return isInitialValue(reflect.ValueOf(v)) 225 }