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  }