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 }