github.com/zly-app/zapp@v1.3.3/pkg/utils/reflect.go (about)

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