github.com/zlyuancn/zstr@v0.0.0-20230412074414-14d6b645962f/is_zero.go (about) 1 /* 2 ------------------------------------------------- 3 Author : Zhang Fan 4 date: 2020/7/22 5 Description : 6 ------------------------------------------------- 7 */ 8 9 package zstr 10 11 import ( 12 "reflect" 13 "unsafe" 14 ) 15 16 // 判断传入参数是否为该类型的零值 17 func IsZero(a interface{}) bool { 18 switch v := a.(type) { 19 case nil: 20 return true 21 case string: 22 return v == "" 23 case []byte: 24 return v == nil 25 case bool: 26 return !v 27 28 case int: 29 return v == 0 30 case int8: 31 return v == 0 32 case int16: 33 return v == 0 34 case int32: 35 return v == 0 36 case int64: 37 return v == 0 38 39 case uint: 40 return v == 0 41 case uint8: 42 return v == 0 43 case uint16: 44 return v == 0 45 case uint32: 46 return v == 0 47 case uint64: 48 return v == 0 49 50 case float32: 51 return v == 0 52 case float64: 53 return v == 0 54 55 case complex64: 56 return v == 0 57 case complex128: 58 return v == 0 59 } 60 61 rv := reflect.Indirect(reflect.ValueOf(a)) // 解包ptr 62 return reflectValueIsZero(rv) 63 } 64 65 func reflectValueIsZero(rv reflect.Value) bool { 66 switch rv.Kind() { 67 case reflect.Invalid: 68 return true 69 case reflect.Array: 70 return arrayIsZero(rv) 71 case reflect.String: 72 return rv.Len() == 0 73 case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice: 74 return rv.IsNil() 75 case reflect.Struct: 76 return structIsZero(rv) 77 } 78 79 nv := reflect.New(rv.Type()).Elem().Interface() // 根据类型创建新的数据 80 81 // 尝试获取值 82 if rv.CanInterface() { 83 return rv.Interface() == nv 84 } 85 86 var p uintptr 87 if rv.CanAddr() { // 尝试获取指针 88 p = rv.UnsafeAddr() 89 } else { 90 // 强行获取指针 91 p = reflect.ValueOf(&rv).Elem().Field(1).UnsafeAddr() // &rv.ptr 92 p = *(*uintptr)(unsafe.Pointer(p)) // rv.ptr 93 } 94 95 temp := reflect.NewAt(rv.Type(), unsafe.Pointer(p)) // 根据指针创建新的数据 96 return temp.Elem().Interface() == nv 97 } 98 99 func structIsZero(rv reflect.Value) bool { 100 num := rv.NumField() 101 for i := 0; i < num; i++ { 102 if !reflectValueIsZero(rv.Field(i)) { 103 return false 104 } 105 } 106 return true 107 } 108 109 func arrayIsZero(rv reflect.Value) bool { 110 num := rv.Len() 111 for i := 0; i < num; i++ { 112 if !reflectValueIsZero(rv.Index(i)) { 113 return false 114 } 115 } 116 return true 117 }