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  }