github.com/gogf/gf/v2@v2.7.4/util/gconv/gconv.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/gogf/gf. 6 7 // Package gconv implements powerful and convenient converting functionality for any types of variables. 8 // 9 // This package should keep much fewer dependencies with other packages. 10 package gconv 11 12 import ( 13 "context" 14 "fmt" 15 "math" 16 "reflect" 17 "strconv" 18 "strings" 19 "time" 20 21 "github.com/gogf/gf/v2/encoding/gbinary" 22 "github.com/gogf/gf/v2/internal/intlog" 23 "github.com/gogf/gf/v2/internal/json" 24 "github.com/gogf/gf/v2/internal/reflection" 25 "github.com/gogf/gf/v2/os/gtime" 26 "github.com/gogf/gf/v2/util/gconv/internal/localinterface" 27 "github.com/gogf/gf/v2/util/gconv/internal/structcache" 28 ) 29 30 var ( 31 // Empty strings. 32 emptyStringMap = map[string]struct{}{ 33 "": {}, 34 "0": {}, 35 "no": {}, 36 "off": {}, 37 "false": {}, 38 } 39 ) 40 41 // IUnmarshalValue is the interface for custom defined types customizing value assignment. 42 // Note that only pointer can implement interface IUnmarshalValue. 43 type IUnmarshalValue = localinterface.IUnmarshalValue 44 45 func init() { 46 // register common converters for internal usage. 47 structcache.RegisterCommonConverter(structcache.CommonConverter{ 48 Int64: Int64, 49 Uint64: Uint64, 50 String: String, 51 Float32: Float32, 52 Float64: Float64, 53 Time: Time, 54 GTime: GTime, 55 Bytes: Bytes, 56 Bool: Bool, 57 }) 58 } 59 60 // Byte converts `any` to byte. 61 func Byte(any interface{}) byte { 62 if v, ok := any.(byte); ok { 63 return v 64 } 65 return Uint8(any) 66 } 67 68 // Bytes converts `any` to []byte. 69 func Bytes(any interface{}) []byte { 70 if any == nil { 71 return nil 72 } 73 switch value := any.(type) { 74 case string: 75 return []byte(value) 76 77 case []byte: 78 return value 79 80 default: 81 if f, ok := value.(localinterface.IBytes); ok { 82 return f.Bytes() 83 } 84 originValueAndKind := reflection.OriginValueAndKind(any) 85 switch originValueAndKind.OriginKind { 86 case reflect.Map: 87 bytes, err := json.Marshal(any) 88 if err != nil { 89 intlog.Errorf(context.TODO(), `%+v`, err) 90 } 91 return bytes 92 93 case reflect.Array, reflect.Slice: 94 var ( 95 ok = true 96 bytes = make([]byte, originValueAndKind.OriginValue.Len()) 97 ) 98 for i := range bytes { 99 int32Value := Int32(originValueAndKind.OriginValue.Index(i).Interface()) 100 if int32Value < 0 || int32Value > math.MaxUint8 { 101 ok = false 102 break 103 } 104 bytes[i] = byte(int32Value) 105 } 106 if ok { 107 return bytes 108 } 109 } 110 return gbinary.Encode(any) 111 } 112 } 113 114 // Rune converts `any` to rune. 115 func Rune(any interface{}) rune { 116 if v, ok := any.(rune); ok { 117 return v 118 } 119 return Int32(any) 120 } 121 122 // Runes converts `any` to []rune. 123 func Runes(any interface{}) []rune { 124 if v, ok := any.([]rune); ok { 125 return v 126 } 127 return []rune(String(any)) 128 } 129 130 // String converts `any` to string. 131 // It's most commonly used converting function. 132 func String(any interface{}) string { 133 if any == nil { 134 return "" 135 } 136 switch value := any.(type) { 137 case int: 138 return strconv.Itoa(value) 139 case int8: 140 return strconv.Itoa(int(value)) 141 case int16: 142 return strconv.Itoa(int(value)) 143 case int32: 144 return strconv.Itoa(int(value)) 145 case int64: 146 return strconv.FormatInt(value, 10) 147 case uint: 148 return strconv.FormatUint(uint64(value), 10) 149 case uint8: 150 return strconv.FormatUint(uint64(value), 10) 151 case uint16: 152 return strconv.FormatUint(uint64(value), 10) 153 case uint32: 154 return strconv.FormatUint(uint64(value), 10) 155 case uint64: 156 return strconv.FormatUint(value, 10) 157 case float32: 158 return strconv.FormatFloat(float64(value), 'f', -1, 32) 159 case float64: 160 return strconv.FormatFloat(value, 'f', -1, 64) 161 case bool: 162 return strconv.FormatBool(value) 163 case string: 164 return value 165 case []byte: 166 return string(value) 167 case time.Time: 168 if value.IsZero() { 169 return "" 170 } 171 return value.String() 172 case *time.Time: 173 if value == nil { 174 return "" 175 } 176 return value.String() 177 case gtime.Time: 178 if value.IsZero() { 179 return "" 180 } 181 return value.String() 182 case *gtime.Time: 183 if value == nil { 184 return "" 185 } 186 return value.String() 187 default: 188 if f, ok := value.(localinterface.IString); ok { 189 // If the variable implements the String() interface, 190 // then use that interface to perform the conversion 191 return f.String() 192 } 193 if f, ok := value.(localinterface.IError); ok { 194 // If the variable implements the Error() interface, 195 // then use that interface to perform the conversion 196 return f.Error() 197 } 198 // Reflect checks. 199 var ( 200 rv = reflect.ValueOf(value) 201 kind = rv.Kind() 202 ) 203 switch kind { 204 case 205 reflect.Chan, 206 reflect.Map, 207 reflect.Slice, 208 reflect.Func, 209 reflect.Interface, 210 reflect.UnsafePointer: 211 if rv.IsNil() { 212 return "" 213 } 214 case reflect.String: 215 return rv.String() 216 case reflect.Ptr: 217 if rv.IsNil() { 218 return "" 219 } 220 return String(rv.Elem().Interface()) 221 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 222 return strconv.FormatInt(rv.Int(), 10) 223 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 224 return strconv.FormatUint(rv.Uint(), 10) 225 case reflect.Uintptr: 226 return strconv.FormatUint(rv.Uint(), 10) 227 case reflect.Float32, reflect.Float64: 228 return strconv.FormatFloat(rv.Float(), 'f', -1, 64) 229 case reflect.Bool: 230 return strconv.FormatBool(rv.Bool()) 231 } 232 // Finally, we use json.Marshal to convert. 233 if jsonContent, err := json.Marshal(value); err != nil { 234 return fmt.Sprint(value) 235 } else { 236 return string(jsonContent) 237 } 238 } 239 } 240 241 // Bool converts `any` to bool. 242 // It returns false if `any` is: false, "", 0, "false", "off", "no", empty slice/map. 243 func Bool(any interface{}) bool { 244 if any == nil { 245 return false 246 } 247 switch value := any.(type) { 248 case bool: 249 return value 250 case []byte: 251 if _, ok := emptyStringMap[strings.ToLower(string(value))]; ok { 252 return false 253 } 254 return true 255 case string: 256 if _, ok := emptyStringMap[strings.ToLower(value)]; ok { 257 return false 258 } 259 return true 260 default: 261 if f, ok := value.(localinterface.IBool); ok { 262 return f.Bool() 263 } 264 rv := reflect.ValueOf(any) 265 switch rv.Kind() { 266 case reflect.Ptr: 267 if rv.IsNil() { 268 return false 269 } 270 if rv.Type().Elem().Kind() == reflect.Bool { 271 return rv.Elem().Bool() 272 } 273 return Bool(rv.Elem().Interface()) 274 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 275 return rv.Int() != 0 276 case reflect.Uintptr, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 277 return rv.Uint() != 0 278 case reflect.Float32, reflect.Float64: 279 return rv.Float() != 0 280 case reflect.Bool: 281 return rv.Bool() 282 // TODO:(Map,Array,Slice,Struct) It might panic here for these types. 283 case reflect.Map, reflect.Array: 284 fallthrough 285 case reflect.Slice: 286 return rv.Len() != 0 287 case reflect.Struct: 288 return true 289 default: 290 s := strings.ToLower(String(any)) 291 if _, ok := emptyStringMap[s]; ok { 292 return false 293 } 294 return true 295 } 296 } 297 } 298 299 // checkJsonAndUnmarshalUseNumber checks if given `any` is JSON formatted string value and does converting using `json.UnmarshalUseNumber`. 300 func checkJsonAndUnmarshalUseNumber(any interface{}, target interface{}) bool { 301 switch r := any.(type) { 302 case []byte: 303 if json.Valid(r) { 304 if err := json.UnmarshalUseNumber(r, &target); err != nil { 305 return false 306 } 307 return true 308 } 309 310 case string: 311 anyAsBytes := []byte(r) 312 if json.Valid(anyAsBytes) { 313 if err := json.UnmarshalUseNumber(anyAsBytes, &target); err != nil { 314 return false 315 } 316 return true 317 } 318 } 319 return false 320 }