github.com/gogf/gf@v1.16.9/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 less dependencies with other packages. 10 package gconv 11 12 import ( 13 "fmt" 14 "github.com/gogf/gf/internal/json" 15 "github.com/gogf/gf/os/gtime" 16 "math" 17 "reflect" 18 "strconv" 19 "strings" 20 "time" 21 22 "github.com/gogf/gf/encoding/gbinary" 23 ) 24 25 type ( 26 // errorStack is the interface for Stack feature. 27 errorStack interface { 28 Error() string 29 Stack() string 30 } 31 ) 32 33 var ( 34 // Empty strings. 35 emptyStringMap = map[string]struct{}{ 36 "": {}, 37 "0": {}, 38 "no": {}, 39 "off": {}, 40 "false": {}, 41 } 42 43 // StructTagPriority defines the default priority tags for Map*/Struct* functions. 44 // Note, the "gconv", "param", "params" tags are used by old version of package. 45 // It is strongly recommended using short tag "c" or "p" instead in the future. 46 StructTagPriority = []string{"gconv", "param", "params", "c", "p", "json"} 47 ) 48 49 type doConvertInput struct { 50 FromValue interface{} // Value that is converted from. 51 ToTypeName string // Target value type name in string. 52 ReferValue interface{} // Referred value, a value in type `ToTypeName`. 53 Extra []interface{} // Extra values for implementing the converting. 54 } 55 56 // doConvert does commonly used types converting. 57 func doConvert(input doConvertInput) interface{} { 58 switch input.ToTypeName { 59 case "int": 60 return Int(input.FromValue) 61 case "*int": 62 if _, ok := input.FromValue.(*int); ok { 63 return input.FromValue 64 } 65 v := Int(input.FromValue) 66 return &v 67 68 case "int8": 69 return Int8(input.FromValue) 70 case "*int8": 71 if _, ok := input.FromValue.(*int8); ok { 72 return input.FromValue 73 } 74 v := Int8(input.FromValue) 75 return &v 76 77 case "int16": 78 return Int16(input.FromValue) 79 case "*int16": 80 if _, ok := input.FromValue.(*int16); ok { 81 return input.FromValue 82 } 83 v := Int16(input.FromValue) 84 return &v 85 86 case "int32": 87 return Int32(input.FromValue) 88 case "*int32": 89 if _, ok := input.FromValue.(*int32); ok { 90 return input.FromValue 91 } 92 v := Int32(input.FromValue) 93 return &v 94 95 case "int64": 96 return Int64(input.FromValue) 97 case "*int64": 98 if _, ok := input.FromValue.(*int64); ok { 99 return input.FromValue 100 } 101 v := Int64(input.FromValue) 102 return &v 103 104 case "uint": 105 return Uint(input.FromValue) 106 case "*uint": 107 if _, ok := input.FromValue.(*uint); ok { 108 return input.FromValue 109 } 110 v := Uint(input.FromValue) 111 return &v 112 113 case "uint8": 114 return Uint8(input.FromValue) 115 case "*uint8": 116 if _, ok := input.FromValue.(*uint8); ok { 117 return input.FromValue 118 } 119 v := Uint8(input.FromValue) 120 return &v 121 122 case "uint16": 123 return Uint16(input.FromValue) 124 case "*uint16": 125 if _, ok := input.FromValue.(*uint16); ok { 126 return input.FromValue 127 } 128 v := Uint16(input.FromValue) 129 return &v 130 131 case "uint32": 132 return Uint32(input.FromValue) 133 case "*uint32": 134 if _, ok := input.FromValue.(*uint32); ok { 135 return input.FromValue 136 } 137 v := Uint32(input.FromValue) 138 return &v 139 140 case "uint64": 141 return Uint64(input.FromValue) 142 case "*uint64": 143 if _, ok := input.FromValue.(*uint64); ok { 144 return input.FromValue 145 } 146 v := Uint64(input.FromValue) 147 return &v 148 149 case "float32": 150 return Float32(input.FromValue) 151 case "*float32": 152 if _, ok := input.FromValue.(*float32); ok { 153 return input.FromValue 154 } 155 v := Float32(input.FromValue) 156 return &v 157 158 case "float64": 159 return Float64(input.FromValue) 160 case "*float64": 161 if _, ok := input.FromValue.(*float64); ok { 162 return input.FromValue 163 } 164 v := Float64(input.FromValue) 165 return &v 166 167 case "bool": 168 return Bool(input.FromValue) 169 case "*bool": 170 if _, ok := input.FromValue.(*bool); ok { 171 return input.FromValue 172 } 173 v := Bool(input.FromValue) 174 return &v 175 176 case "string": 177 return String(input.FromValue) 178 case "*string": 179 if _, ok := input.FromValue.(*string); ok { 180 return input.FromValue 181 } 182 v := String(input.FromValue) 183 return &v 184 185 case "[]byte": 186 return Bytes(input.FromValue) 187 case "[]int": 188 return Ints(input.FromValue) 189 case "[]int32": 190 return Int32s(input.FromValue) 191 case "[]int64": 192 return Int64s(input.FromValue) 193 case "[]uint": 194 return Uints(input.FromValue) 195 case "[]uint8": 196 return Bytes(input.FromValue) 197 case "[]uint32": 198 return Uint32s(input.FromValue) 199 case "[]uint64": 200 return Uint64s(input.FromValue) 201 case "[]float32": 202 return Float32s(input.FromValue) 203 case "[]float64": 204 return Float64s(input.FromValue) 205 case "[]string": 206 return Strings(input.FromValue) 207 208 case "Time", "time.Time": 209 if len(input.Extra) > 0 { 210 return Time(input.FromValue, String(input.Extra[0])) 211 } 212 return Time(input.FromValue) 213 case "*time.Time": 214 var v interface{} 215 if len(input.Extra) > 0 { 216 v = Time(input.FromValue, String(input.Extra[0])) 217 } else { 218 if _, ok := input.FromValue.(*time.Time); ok { 219 return input.FromValue 220 } 221 v = Time(input.FromValue) 222 } 223 return &v 224 225 case "GTime", "gtime.Time": 226 if len(input.Extra) > 0 { 227 if v := GTime(input.FromValue, String(input.Extra[0])); v != nil { 228 return *v 229 } else { 230 return *gtime.New() 231 } 232 } 233 if v := GTime(input.FromValue); v != nil { 234 return *v 235 } else { 236 return *gtime.New() 237 } 238 case "*gtime.Time": 239 if len(input.Extra) > 0 { 240 if v := GTime(input.FromValue, String(input.Extra[0])); v != nil { 241 return v 242 } else { 243 return gtime.New() 244 } 245 } 246 if v := GTime(input.FromValue); v != nil { 247 return v 248 } else { 249 return gtime.New() 250 } 251 252 case "Duration", "time.Duration": 253 return Duration(input.FromValue) 254 case "*time.Duration": 255 if _, ok := input.FromValue.(*time.Duration); ok { 256 return input.FromValue 257 } 258 v := Duration(input.FromValue) 259 return &v 260 261 case "map[string]string": 262 return MapStrStr(input.FromValue) 263 264 case "map[string]interface{}": 265 return Map(input.FromValue) 266 267 case "[]map[string]interface{}": 268 return Maps(input.FromValue) 269 270 default: 271 if input.ReferValue != nil { 272 var ( 273 referReflectValue reflect.Value 274 ) 275 if v, ok := input.ReferValue.(reflect.Value); ok { 276 referReflectValue = v 277 } else { 278 referReflectValue = reflect.ValueOf(input.ReferValue) 279 } 280 input.ToTypeName = referReflectValue.Kind().String() 281 input.ReferValue = nil 282 return reflect.ValueOf(doConvert(input)).Convert(referReflectValue.Type()).Interface() 283 } 284 return input.FromValue 285 } 286 } 287 288 // Convert converts the variable `fromValue` to the type `toTypeName`, the type `toTypeName` is specified by string. 289 // The optional parameter `extraParams` is used for additional necessary parameter for this conversion. 290 // It supports common types conversion as its conversion based on type name string. 291 func Convert(fromValue interface{}, toTypeName string, extraParams ...interface{}) interface{} { 292 return doConvert(doConvertInput{ 293 FromValue: fromValue, 294 ToTypeName: toTypeName, 295 ReferValue: nil, 296 Extra: extraParams, 297 }) 298 } 299 300 // Byte converts `any` to byte. 301 func Byte(any interface{}) byte { 302 if v, ok := any.(byte); ok { 303 return v 304 } 305 return Uint8(any) 306 } 307 308 // Bytes converts `any` to []byte. 309 func Bytes(any interface{}) []byte { 310 if any == nil { 311 return nil 312 } 313 switch value := any.(type) { 314 case string: 315 return []byte(value) 316 case []byte: 317 return value 318 default: 319 if f, ok := value.(apiBytes); ok { 320 return f.Bytes() 321 } 322 var ( 323 reflectValue = reflect.ValueOf(any) 324 reflectKind = reflectValue.Kind() 325 ) 326 for reflectKind == reflect.Ptr { 327 reflectValue = reflectValue.Elem() 328 reflectKind = reflectValue.Kind() 329 } 330 switch reflectKind { 331 case reflect.Array, reflect.Slice: 332 var ( 333 ok = true 334 bytes = make([]byte, reflectValue.Len()) 335 ) 336 for i, _ := range bytes { 337 int32Value := Int32(reflectValue.Index(i).Interface()) 338 if int32Value < 0 || int32Value > math.MaxUint8 { 339 ok = false 340 break 341 } 342 bytes[i] = byte(int32Value) 343 } 344 if ok { 345 return bytes 346 } 347 } 348 return gbinary.Encode(any) 349 } 350 } 351 352 // Rune converts `any` to rune. 353 func Rune(any interface{}) rune { 354 if v, ok := any.(rune); ok { 355 return v 356 } 357 return Int32(any) 358 } 359 360 // Runes converts `any` to []rune. 361 func Runes(any interface{}) []rune { 362 if v, ok := any.([]rune); ok { 363 return v 364 } 365 return []rune(String(any)) 366 } 367 368 // String converts `any` to string. 369 // It's most commonly used converting function. 370 func String(any interface{}) string { 371 if any == nil { 372 return "" 373 } 374 switch value := any.(type) { 375 case int: 376 return strconv.Itoa(value) 377 case int8: 378 return strconv.Itoa(int(value)) 379 case int16: 380 return strconv.Itoa(int(value)) 381 case int32: 382 return strconv.Itoa(int(value)) 383 case int64: 384 return strconv.FormatInt(value, 10) 385 case uint: 386 return strconv.FormatUint(uint64(value), 10) 387 case uint8: 388 return strconv.FormatUint(uint64(value), 10) 389 case uint16: 390 return strconv.FormatUint(uint64(value), 10) 391 case uint32: 392 return strconv.FormatUint(uint64(value), 10) 393 case uint64: 394 return strconv.FormatUint(value, 10) 395 case float32: 396 return strconv.FormatFloat(float64(value), 'f', -1, 32) 397 case float64: 398 return strconv.FormatFloat(value, 'f', -1, 64) 399 case bool: 400 return strconv.FormatBool(value) 401 case string: 402 return value 403 case []byte: 404 return string(value) 405 case time.Time: 406 if value.IsZero() { 407 return "" 408 } 409 return value.String() 410 case *time.Time: 411 if value == nil { 412 return "" 413 } 414 return value.String() 415 case gtime.Time: 416 if value.IsZero() { 417 return "" 418 } 419 return value.String() 420 case *gtime.Time: 421 if value == nil { 422 return "" 423 } 424 return value.String() 425 default: 426 // Empty checks. 427 if value == nil { 428 return "" 429 } 430 if f, ok := value.(apiString); ok { 431 // If the variable implements the String() interface, 432 // then use that interface to perform the conversion 433 return f.String() 434 } 435 if f, ok := value.(apiError); ok { 436 // If the variable implements the Error() interface, 437 // then use that interface to perform the conversion 438 return f.Error() 439 } 440 // Reflect checks. 441 var ( 442 rv = reflect.ValueOf(value) 443 kind = rv.Kind() 444 ) 445 switch kind { 446 case reflect.Chan, 447 reflect.Map, 448 reflect.Slice, 449 reflect.Func, 450 reflect.Ptr, 451 reflect.Interface, 452 reflect.UnsafePointer: 453 if rv.IsNil() { 454 return "" 455 } 456 case reflect.String: 457 return rv.String() 458 } 459 if kind == reflect.Ptr { 460 return String(rv.Elem().Interface()) 461 } 462 // Finally, we use json.Marshal to convert. 463 if jsonContent, err := json.Marshal(value); err != nil { 464 return fmt.Sprint(value) 465 } else { 466 return string(jsonContent) 467 } 468 } 469 } 470 471 // Bool converts `any` to bool. 472 // It returns false if `any` is: false, "", 0, "false", "off", "no", empty slice/map. 473 func Bool(any interface{}) bool { 474 if any == nil { 475 return false 476 } 477 switch value := any.(type) { 478 case bool: 479 return value 480 case []byte: 481 if _, ok := emptyStringMap[strings.ToLower(string(value))]; ok { 482 return false 483 } 484 return true 485 case string: 486 if _, ok := emptyStringMap[strings.ToLower(value)]; ok { 487 return false 488 } 489 return true 490 default: 491 if f, ok := value.(apiBool); ok { 492 return f.Bool() 493 } 494 rv := reflect.ValueOf(any) 495 switch rv.Kind() { 496 case reflect.Ptr: 497 return !rv.IsNil() 498 case reflect.Map: 499 fallthrough 500 case reflect.Array: 501 fallthrough 502 case reflect.Slice: 503 return rv.Len() != 0 504 case reflect.Struct: 505 return true 506 default: 507 s := strings.ToLower(String(any)) 508 if _, ok := emptyStringMap[s]; ok { 509 return false 510 } 511 return true 512 } 513 } 514 } 515 516 // Int converts `any` to int. 517 func Int(any interface{}) int { 518 if any == nil { 519 return 0 520 } 521 if v, ok := any.(int); ok { 522 return v 523 } 524 return int(Int64(any)) 525 } 526 527 // Int8 converts `any` to int8. 528 func Int8(any interface{}) int8 { 529 if any == nil { 530 return 0 531 } 532 if v, ok := any.(int8); ok { 533 return v 534 } 535 return int8(Int64(any)) 536 } 537 538 // Int16 converts `any` to int16. 539 func Int16(any interface{}) int16 { 540 if any == nil { 541 return 0 542 } 543 if v, ok := any.(int16); ok { 544 return v 545 } 546 return int16(Int64(any)) 547 } 548 549 // Int32 converts `any` to int32. 550 func Int32(any interface{}) int32 { 551 if any == nil { 552 return 0 553 } 554 if v, ok := any.(int32); ok { 555 return v 556 } 557 return int32(Int64(any)) 558 } 559 560 // Int64 converts `any` to int64. 561 func Int64(any interface{}) int64 { 562 if any == nil { 563 return 0 564 } 565 switch value := any.(type) { 566 case int: 567 return int64(value) 568 case int8: 569 return int64(value) 570 case int16: 571 return int64(value) 572 case int32: 573 return int64(value) 574 case int64: 575 return value 576 case uint: 577 return int64(value) 578 case uint8: 579 return int64(value) 580 case uint16: 581 return int64(value) 582 case uint32: 583 return int64(value) 584 case uint64: 585 return int64(value) 586 case float32: 587 return int64(value) 588 case float64: 589 return int64(value) 590 case bool: 591 if value { 592 return 1 593 } 594 return 0 595 case []byte: 596 return gbinary.DecodeToInt64(value) 597 default: 598 if f, ok := value.(apiInt64); ok { 599 return f.Int64() 600 } 601 s := String(value) 602 isMinus := false 603 if len(s) > 0 { 604 if s[0] == '-' { 605 isMinus = true 606 s = s[1:] 607 } else if s[0] == '+' { 608 s = s[1:] 609 } 610 } 611 // Hexadecimal 612 if len(s) > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X') { 613 if v, e := strconv.ParseInt(s[2:], 16, 64); e == nil { 614 if isMinus { 615 return -v 616 } 617 return v 618 } 619 } 620 // Octal 621 if len(s) > 1 && s[0] == '0' { 622 if v, e := strconv.ParseInt(s[1:], 8, 64); e == nil { 623 if isMinus { 624 return -v 625 } 626 return v 627 } 628 } 629 // Decimal 630 if v, e := strconv.ParseInt(s, 10, 64); e == nil { 631 if isMinus { 632 return -v 633 } 634 return v 635 } 636 // Float64 637 return int64(Float64(value)) 638 } 639 } 640 641 // Uint converts `any` to uint. 642 func Uint(any interface{}) uint { 643 if any == nil { 644 return 0 645 } 646 if v, ok := any.(uint); ok { 647 return v 648 } 649 return uint(Uint64(any)) 650 } 651 652 // Uint8 converts `any` to uint8. 653 func Uint8(any interface{}) uint8 { 654 if any == nil { 655 return 0 656 } 657 if v, ok := any.(uint8); ok { 658 return v 659 } 660 return uint8(Uint64(any)) 661 } 662 663 // Uint16 converts `any` to uint16. 664 func Uint16(any interface{}) uint16 { 665 if any == nil { 666 return 0 667 } 668 if v, ok := any.(uint16); ok { 669 return v 670 } 671 return uint16(Uint64(any)) 672 } 673 674 // Uint32 converts `any` to uint32. 675 func Uint32(any interface{}) uint32 { 676 if any == nil { 677 return 0 678 } 679 if v, ok := any.(uint32); ok { 680 return v 681 } 682 return uint32(Uint64(any)) 683 } 684 685 // Uint64 converts `any` to uint64. 686 func Uint64(any interface{}) uint64 { 687 if any == nil { 688 return 0 689 } 690 switch value := any.(type) { 691 case int: 692 return uint64(value) 693 case int8: 694 return uint64(value) 695 case int16: 696 return uint64(value) 697 case int32: 698 return uint64(value) 699 case int64: 700 return uint64(value) 701 case uint: 702 return uint64(value) 703 case uint8: 704 return uint64(value) 705 case uint16: 706 return uint64(value) 707 case uint32: 708 return uint64(value) 709 case uint64: 710 return value 711 case float32: 712 return uint64(value) 713 case float64: 714 return uint64(value) 715 case bool: 716 if value { 717 return 1 718 } 719 return 0 720 case []byte: 721 return gbinary.DecodeToUint64(value) 722 default: 723 if f, ok := value.(apiUint64); ok { 724 return f.Uint64() 725 } 726 s := String(value) 727 // Hexadecimal 728 if len(s) > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X') { 729 if v, e := strconv.ParseUint(s[2:], 16, 64); e == nil { 730 return v 731 } 732 } 733 // Octal 734 if len(s) > 1 && s[0] == '0' { 735 if v, e := strconv.ParseUint(s[1:], 8, 64); e == nil { 736 return v 737 } 738 } 739 // Decimal 740 if v, e := strconv.ParseUint(s, 10, 64); e == nil { 741 return v 742 } 743 // Float64 744 return uint64(Float64(value)) 745 } 746 } 747 748 // Float32 converts `any` to float32. 749 func Float32(any interface{}) float32 { 750 if any == nil { 751 return 0 752 } 753 switch value := any.(type) { 754 case float32: 755 return value 756 case float64: 757 return float32(value) 758 case []byte: 759 return gbinary.DecodeToFloat32(value) 760 default: 761 if f, ok := value.(apiFloat32); ok { 762 return f.Float32() 763 } 764 v, _ := strconv.ParseFloat(String(any), 64) 765 return float32(v) 766 } 767 } 768 769 // Float64 converts `any` to float64. 770 func Float64(any interface{}) float64 { 771 if any == nil { 772 return 0 773 } 774 switch value := any.(type) { 775 case float32: 776 return float64(value) 777 case float64: 778 return value 779 case []byte: 780 return gbinary.DecodeToFloat64(value) 781 default: 782 if f, ok := value.(apiFloat64); ok { 783 return f.Float64() 784 } 785 v, _ := strconv.ParseFloat(String(any), 64) 786 return v 787 } 788 }