github.com/gogf/gf@v1.16.9/internal/empty/empty.go (about)

     1  // Copyright GoFrame gf 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 empty provides functions for checking empty/nil variables.
     8  package empty
     9  
    10  import (
    11  	"reflect"
    12  	"time"
    13  )
    14  
    15  // apiString is used for type assert api for String().
    16  type apiString interface {
    17  	String() string
    18  }
    19  
    20  // apiInterfaces is used for type assert api for Interfaces.
    21  type apiInterfaces interface {
    22  	Interfaces() []interface{}
    23  }
    24  
    25  // apiMapStrAny is the interface support for converting struct parameter to map.
    26  type apiMapStrAny interface {
    27  	MapStrAny() map[string]interface{}
    28  }
    29  
    30  type apiTime interface {
    31  	Date() (year int, month time.Month, day int)
    32  	IsZero() bool
    33  }
    34  
    35  // IsEmpty checks whether given `value` empty.
    36  // It returns true if `value` is in: 0, nil, false, "", len(slice/map/chan) == 0,
    37  // or else it returns false.
    38  func IsEmpty(value interface{}) bool {
    39  	if value == nil {
    40  		return true
    41  	}
    42  	// It firstly checks the variable as common types using assertion to enhance the performance,
    43  	// and then using reflection.
    44  	switch value := value.(type) {
    45  	case int:
    46  		return value == 0
    47  	case int8:
    48  		return value == 0
    49  	case int16:
    50  		return value == 0
    51  	case int32:
    52  		return value == 0
    53  	case int64:
    54  		return value == 0
    55  	case uint:
    56  		return value == 0
    57  	case uint8:
    58  		return value == 0
    59  	case uint16:
    60  		return value == 0
    61  	case uint32:
    62  		return value == 0
    63  	case uint64:
    64  		return value == 0
    65  	case float32:
    66  		return value == 0
    67  	case float64:
    68  		return value == 0
    69  	case bool:
    70  		return value == false
    71  	case string:
    72  		return value == ""
    73  	case []byte:
    74  		return len(value) == 0
    75  	case []rune:
    76  		return len(value) == 0
    77  	case []int:
    78  		return len(value) == 0
    79  	case []string:
    80  		return len(value) == 0
    81  	case []float32:
    82  		return len(value) == 0
    83  	case []float64:
    84  		return len(value) == 0
    85  	case map[string]interface{}:
    86  		return len(value) == 0
    87  	default:
    88  		// =========================
    89  		// Common interfaces checks.
    90  		// =========================
    91  		if f, ok := value.(apiTime); ok {
    92  			if f == nil {
    93  				return true
    94  			}
    95  			return f.IsZero()
    96  		}
    97  		if f, ok := value.(apiString); ok {
    98  			if f == nil {
    99  				return true
   100  			}
   101  			return f.String() == ""
   102  		}
   103  		if f, ok := value.(apiInterfaces); ok {
   104  			if f == nil {
   105  				return true
   106  			}
   107  			return len(f.Interfaces()) == 0
   108  		}
   109  		if f, ok := value.(apiMapStrAny); ok {
   110  			if f == nil {
   111  				return true
   112  			}
   113  			return len(f.MapStrAny()) == 0
   114  		}
   115  		// Finally using reflect.
   116  		var rv reflect.Value
   117  		if v, ok := value.(reflect.Value); ok {
   118  			rv = v
   119  		} else {
   120  			rv = reflect.ValueOf(value)
   121  		}
   122  
   123  		switch rv.Kind() {
   124  		case reflect.Bool:
   125  			return !rv.Bool()
   126  		case reflect.Int,
   127  			reflect.Int8,
   128  			reflect.Int16,
   129  			reflect.Int32,
   130  			reflect.Int64:
   131  			return rv.Int() == 0
   132  		case reflect.Uint,
   133  			reflect.Uint8,
   134  			reflect.Uint16,
   135  			reflect.Uint32,
   136  			reflect.Uint64,
   137  			reflect.Uintptr:
   138  			return rv.Uint() == 0
   139  		case reflect.Float32,
   140  			reflect.Float64:
   141  			return rv.Float() == 0
   142  		case reflect.String:
   143  			return rv.Len() == 0
   144  		case reflect.Struct:
   145  			for i := 0; i < rv.NumField(); i++ {
   146  				if !IsEmpty(rv) {
   147  					return false
   148  				}
   149  			}
   150  			return true
   151  		case reflect.Chan,
   152  			reflect.Map,
   153  			reflect.Slice,
   154  			reflect.Array:
   155  			return rv.Len() == 0
   156  		case reflect.Func,
   157  			reflect.Ptr,
   158  			reflect.Interface,
   159  			reflect.UnsafePointer:
   160  			if rv.IsNil() {
   161  				return true
   162  			}
   163  		}
   164  	}
   165  	return false
   166  }
   167  
   168  // IsEmptyLength checks whether given `value` is empty length.
   169  // It returns true if `value` is in: nil, "", len(slice/map/chan) == 0,
   170  // or else it returns false.
   171  //func IsEmptyLength(value interface{}) bool {
   172  //	if value == nil {
   173  //		return true
   174  //	}
   175  //	// It firstly checks the variable as common types using assertion to enhance the performance,
   176  //	// and then using reflection.
   177  //	switch value := value.(type) {
   178  //	case
   179  //		int,
   180  //		int8,
   181  //		int16,
   182  //		int32,
   183  //		int64,
   184  //		uint,
   185  //		uint8,
   186  //		uint16,
   187  //		uint32,
   188  //		uint64,
   189  //		float32,
   190  //		float64,
   191  //		bool:
   192  //		return false
   193  //	case string:
   194  //		return value == ""
   195  //	case []byte:
   196  //		return len(value) == 0
   197  //	case []rune:
   198  //		return len(value) == 0
   199  //	case []int:
   200  //		return len(value) == 0
   201  //	case []string:
   202  //		return len(value) == 0
   203  //	case []float32:
   204  //		return len(value) == 0
   205  //	case []float64:
   206  //		return len(value) == 0
   207  //	case map[string]interface{}:
   208  //		return len(value) == 0
   209  //	default:
   210  //		// =========================
   211  //		// Common interfaces checks.
   212  //		// =========================
   213  //		if f, ok := value.(apiTime); ok {
   214  //			if f == nil {
   215  //				return true
   216  //			}
   217  //			return f.IsZero()
   218  //		}
   219  //		if f, ok := value.(apiString); ok {
   220  //			if f == nil {
   221  //				return true
   222  //			}
   223  //			return f.String() == ""
   224  //		}
   225  //		if f, ok := value.(apiInterfaces); ok {
   226  //			if f == nil {
   227  //				return true
   228  //			}
   229  //			return len(f.Interfaces()) == 0
   230  //		}
   231  //		if f, ok := value.(apiMapStrAny); ok {
   232  //			if f == nil {
   233  //				return true
   234  //			}
   235  //			return len(f.MapStrAny()) == 0
   236  //		}
   237  //		// Finally using reflect.
   238  //		var rv reflect.Value
   239  //		if v, ok := value.(reflect.Value); ok {
   240  //			rv = v
   241  //		} else {
   242  //			rv = reflect.ValueOf(value)
   243  //		}
   244  //
   245  //		switch rv.Kind() {
   246  //		case
   247  //			reflect.Int,
   248  //			reflect.Int8,
   249  //			reflect.Int16,
   250  //			reflect.Int32,
   251  //			reflect.Int64,
   252  //			reflect.Uint,
   253  //			reflect.Uint8,
   254  //			reflect.Uint16,
   255  //			reflect.Uint32,
   256  //			reflect.Uint64,
   257  //			reflect.Uintptr,
   258  //			reflect.Float32,
   259  //			reflect.Float64,
   260  //			reflect.Bool:
   261  //			return false
   262  //		case reflect.String:
   263  //			return rv.Len() == 0
   264  //		case reflect.Struct:
   265  //			for i := 0; i < rv.NumField(); i++ {
   266  //				if !IsEmpty(rv) {
   267  //					return false
   268  //				}
   269  //			}
   270  //			return true
   271  //		case reflect.Chan,
   272  //			reflect.Map,
   273  //			reflect.Slice,
   274  //			reflect.Array:
   275  //			return rv.Len() == 0
   276  //		case reflect.Func,
   277  //			reflect.Ptr,
   278  //			reflect.Interface,
   279  //			reflect.UnsafePointer:
   280  //			if rv.IsNil() {
   281  //				return true
   282  //			}
   283  //		}
   284  //	}
   285  //	return false
   286  //}
   287  
   288  // IsNil checks whether given `value` is nil.
   289  // Parameter `traceSource` is used for tracing to the source variable if given `value` is type of pinter
   290  // that also points to a pointer. It returns nil if the source is nil when `traceSource` is true.
   291  // Note that it might use reflect feature which affects performance a little.
   292  func IsNil(value interface{}, traceSource ...bool) bool {
   293  	if value == nil {
   294  		return true
   295  	}
   296  	var rv reflect.Value
   297  	if v, ok := value.(reflect.Value); ok {
   298  		rv = v
   299  	} else {
   300  		rv = reflect.ValueOf(value)
   301  	}
   302  	switch rv.Kind() {
   303  	case reflect.Chan,
   304  		reflect.Map,
   305  		reflect.Slice,
   306  		reflect.Func,
   307  		reflect.Interface,
   308  		reflect.UnsafePointer:
   309  		return !rv.IsValid() || rv.IsNil()
   310  
   311  	case reflect.Ptr:
   312  		if len(traceSource) > 0 && traceSource[0] {
   313  			for rv.Kind() == reflect.Ptr {
   314  				rv = rv.Elem()
   315  			}
   316  			if !rv.IsValid() {
   317  				return true
   318  			}
   319  			if rv.Kind() == reflect.Ptr {
   320  				return rv.IsNil()
   321  			}
   322  		} else {
   323  			return !rv.IsValid() || rv.IsNil()
   324  		}
   325  	}
   326  	return false
   327  }