github.com/wangyougui/gf/v2@v2.6.5/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/wangyougui/gf. 6 7 // Package gconv implements powerful and convenient converting functionality for any types of variables. 8 // 9 // This package should keep much less 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/wangyougui/gf/v2/encoding/gbinary" 22 "github.com/wangyougui/gf/v2/internal/intlog" 23 "github.com/wangyougui/gf/v2/internal/json" 24 "github.com/wangyougui/gf/v2/internal/reflection" 25 "github.com/wangyougui/gf/v2/os/gtime" 26 "github.com/wangyougui/gf/v2/util/gtag" 27 ) 28 29 var ( 30 // Empty strings. 31 emptyStringMap = map[string]struct{}{ 32 "": {}, 33 "0": {}, 34 "no": {}, 35 "off": {}, 36 "false": {}, 37 } 38 39 // StructTagPriority defines the default priority tags for Map*/Struct* functions. 40 // Note that, the `gconv/param` tags are used by old version of package. 41 // It is strongly recommended using short tag `c/p` instead in the future. 42 StructTagPriority = gtag.StructTagPriority 43 ) 44 45 // Byte converts `any` to byte. 46 func Byte(any interface{}) byte { 47 if v, ok := any.(byte); ok { 48 return v 49 } 50 return Uint8(any) 51 } 52 53 // Bytes converts `any` to []byte. 54 func Bytes(any interface{}) []byte { 55 if any == nil { 56 return nil 57 } 58 switch value := any.(type) { 59 case string: 60 return []byte(value) 61 62 case []byte: 63 return value 64 65 default: 66 if f, ok := value.(iBytes); ok { 67 return f.Bytes() 68 } 69 originValueAndKind := reflection.OriginValueAndKind(any) 70 switch originValueAndKind.OriginKind { 71 case reflect.Map: 72 bytes, err := json.Marshal(any) 73 if err != nil { 74 intlog.Errorf(context.TODO(), `%+v`, err) 75 } 76 return bytes 77 78 case reflect.Array, reflect.Slice: 79 var ( 80 ok = true 81 bytes = make([]byte, originValueAndKind.OriginValue.Len()) 82 ) 83 for i := range bytes { 84 int32Value := Int32(originValueAndKind.OriginValue.Index(i).Interface()) 85 if int32Value < 0 || int32Value > math.MaxUint8 { 86 ok = false 87 break 88 } 89 bytes[i] = byte(int32Value) 90 } 91 if ok { 92 return bytes 93 } 94 } 95 return gbinary.Encode(any) 96 } 97 } 98 99 // Rune converts `any` to rune. 100 func Rune(any interface{}) rune { 101 if v, ok := any.(rune); ok { 102 return v 103 } 104 return Int32(any) 105 } 106 107 // Runes converts `any` to []rune. 108 func Runes(any interface{}) []rune { 109 if v, ok := any.([]rune); ok { 110 return v 111 } 112 return []rune(String(any)) 113 } 114 115 // String converts `any` to string. 116 // It's most commonly used converting function. 117 func String(any interface{}) string { 118 if any == nil { 119 return "" 120 } 121 switch value := any.(type) { 122 case int: 123 return strconv.Itoa(value) 124 case int8: 125 return strconv.Itoa(int(value)) 126 case int16: 127 return strconv.Itoa(int(value)) 128 case int32: 129 return strconv.Itoa(int(value)) 130 case int64: 131 return strconv.FormatInt(value, 10) 132 case uint: 133 return strconv.FormatUint(uint64(value), 10) 134 case uint8: 135 return strconv.FormatUint(uint64(value), 10) 136 case uint16: 137 return strconv.FormatUint(uint64(value), 10) 138 case uint32: 139 return strconv.FormatUint(uint64(value), 10) 140 case uint64: 141 return strconv.FormatUint(value, 10) 142 case float32: 143 return strconv.FormatFloat(float64(value), 'f', -1, 32) 144 case float64: 145 return strconv.FormatFloat(value, 'f', -1, 64) 146 case bool: 147 return strconv.FormatBool(value) 148 case string: 149 return value 150 case []byte: 151 return string(value) 152 case time.Time: 153 if value.IsZero() { 154 return "" 155 } 156 return value.String() 157 case *time.Time: 158 if value == nil { 159 return "" 160 } 161 return value.String() 162 case gtime.Time: 163 if value.IsZero() { 164 return "" 165 } 166 return value.String() 167 case *gtime.Time: 168 if value == nil { 169 return "" 170 } 171 return value.String() 172 default: 173 // Empty checks. 174 if value == nil { 175 return "" 176 } 177 if f, ok := value.(iString); ok { 178 // If the variable implements the String() interface, 179 // then use that interface to perform the conversion 180 return f.String() 181 } 182 if f, ok := value.(iError); ok { 183 // If the variable implements the Error() interface, 184 // then use that interface to perform the conversion 185 return f.Error() 186 } 187 // Reflect checks. 188 var ( 189 rv = reflect.ValueOf(value) 190 kind = rv.Kind() 191 ) 192 switch kind { 193 case reflect.Chan, 194 reflect.Map, 195 reflect.Slice, 196 reflect.Func, 197 reflect.Ptr, 198 reflect.Interface, 199 reflect.UnsafePointer: 200 if rv.IsNil() { 201 return "" 202 } 203 case reflect.String: 204 return rv.String() 205 } 206 if kind == reflect.Ptr { 207 return String(rv.Elem().Interface()) 208 } 209 // Finally, we use json.Marshal to convert. 210 if jsonContent, err := json.Marshal(value); err != nil { 211 return fmt.Sprint(value) 212 } else { 213 return string(jsonContent) 214 } 215 } 216 } 217 218 // Bool converts `any` to bool. 219 // It returns false if `any` is: false, "", 0, "false", "off", "no", empty slice/map. 220 func Bool(any interface{}) bool { 221 if any == nil { 222 return false 223 } 224 switch value := any.(type) { 225 case bool: 226 return value 227 case []byte: 228 if _, ok := emptyStringMap[strings.ToLower(string(value))]; ok { 229 return false 230 } 231 return true 232 case string: 233 if _, ok := emptyStringMap[strings.ToLower(value)]; ok { 234 return false 235 } 236 return true 237 default: 238 if f, ok := value.(iBool); ok { 239 return f.Bool() 240 } 241 rv := reflect.ValueOf(any) 242 switch rv.Kind() { 243 case reflect.Ptr: 244 return !rv.IsNil() 245 case reflect.Map: 246 fallthrough 247 case reflect.Array: 248 fallthrough 249 case reflect.Slice: 250 return rv.Len() != 0 251 case reflect.Struct: 252 return true 253 default: 254 s := strings.ToLower(String(any)) 255 if _, ok := emptyStringMap[s]; ok { 256 return false 257 } 258 return true 259 } 260 } 261 } 262 263 // checkJsonAndUnmarshalUseNumber checks if given `any` is JSON formatted string value and does converting using `json.UnmarshalUseNumber`. 264 func checkJsonAndUnmarshalUseNumber(any interface{}, target interface{}) bool { 265 switch r := any.(type) { 266 case []byte: 267 if json.Valid(r) { 268 if err := json.UnmarshalUseNumber(r, &target); err != nil { 269 return false 270 } 271 return true 272 } 273 274 case string: 275 anyAsBytes := []byte(r) 276 if json.Valid(anyAsBytes) { 277 if err := json.UnmarshalUseNumber(anyAsBytes, &target); err != nil { 278 return false 279 } 280 return true 281 } 282 } 283 return false 284 }