github.com/RevenueMonster/sqlike@v1.0.6/reflext/helper.go (about)

     1  package reflext
     2  
     3  import (
     4  	"reflect"
     5  )
     6  
     7  // Zeroer :
     8  type Zeroer interface {
     9  	IsZero() bool
    10  }
    11  
    12  // Init : initialise the first level of reflect.Value
    13  func Init(v reflect.Value) reflect.Value {
    14  	if v.Kind() == reflect.Ptr && v.IsNil() {
    15  		v.Set(reflect.New(v.Type().Elem()))
    16  	}
    17  	if v.Kind() == reflect.Map && v.IsNil() {
    18  		v.Set(reflect.MakeMap(v.Type()))
    19  	}
    20  	if v.Kind() == reflect.Slice && v.IsNil() {
    21  		v.Set(reflect.MakeSlice(v.Type(), 0, 0))
    22  	}
    23  	return v
    24  }
    25  
    26  // IndirectInit : initialise reflect.Value till the deep level
    27  func IndirectInit(v reflect.Value) reflect.Value {
    28  	for v.Kind() == reflect.Ptr {
    29  		if v.IsNil() {
    30  			v.Set(reflect.New(v.Type().Elem()))
    31  		}
    32  		v = v.Elem()
    33  	}
    34  	return v
    35  }
    36  
    37  // ValueOf : this is the replacement for reflect.ValueOf()
    38  func ValueOf(i interface{}) reflect.Value {
    39  	if x, ok := i.(reflect.Value); ok {
    40  		return x
    41  	}
    42  	return reflect.ValueOf(i)
    43  }
    44  
    45  // TypeOf : this is the replacement for reflect.TypeOf()
    46  func TypeOf(i interface{}) reflect.Type {
    47  	if x, ok := i.(reflect.Type); ok {
    48  		return x
    49  	}
    50  	return reflect.TypeOf(i)
    51  }
    52  
    53  // Deref : this is the replacement for reflect.Elem()
    54  func Deref(t reflect.Type) reflect.Type {
    55  	for t.Kind() == reflect.Ptr {
    56  		t = t.Elem()
    57  	}
    58  	return t
    59  }
    60  
    61  // Indirect : this is the replacement for reflect.Indirect()
    62  func Indirect(v reflect.Value) reflect.Value {
    63  	for v.Kind() == reflect.Ptr {
    64  		if v.IsNil() {
    65  			break
    66  		}
    67  		v = v.Elem()
    68  	}
    69  	return v
    70  }
    71  
    72  // IsNull : determine the reflect.Value is null or not
    73  func IsNull(v reflect.Value) bool {
    74  	if !v.IsValid() {
    75  		return true
    76  	}
    77  
    78  	k := v.Kind()
    79  	return (k == reflect.Ptr ||
    80  		k == reflect.Slice ||
    81  		k == reflect.Map ||
    82  		k == reflect.Interface ||
    83  		k == reflect.Func) && v.IsNil()
    84  }
    85  
    86  // Zero :
    87  func Zero(t reflect.Type) (v reflect.Value) {
    88  	v = reflect.New(t)
    89  	vi := v.Elem()
    90  	for vi.Kind() == reflect.Ptr && vi.IsNil() {
    91  		vi.Set(reflect.New(vi.Type().Elem()))
    92  		vi = vi.Elem()
    93  	}
    94  	return v.Elem()
    95  }
    96  
    97  // IsNullable : determine whether is nullable data type
    98  func IsNullable(t reflect.Type) bool {
    99  	if t == nil {
   100  		return true
   101  	}
   102  
   103  	k := t.Kind()
   104  	return k == reflect.Ptr ||
   105  		k == reflect.Slice ||
   106  		k == reflect.Map ||
   107  		k == reflect.Interface ||
   108  		k == reflect.Func ||
   109  		k == reflect.Chan
   110  }
   111  
   112  // IsKind : compare and check the respective reflect.Kind
   113  func IsKind(t reflect.Type, k reflect.Kind) bool {
   114  	if t == nil {
   115  		return k == reflect.Interface
   116  	}
   117  	return t.Kind() == k
   118  }
   119  
   120  /*
   121  IsZero : determine is zero value
   122  1. string => empty string
   123  2. bool => false
   124  3. function => nil
   125  4. map => nil (uninitialized map)
   126  5. slice => nil (uninitialized slice)
   127  */
   128  func IsZero(v reflect.Value) bool {
   129  	if !v.IsValid() {
   130  		return true
   131  	}
   132  
   133  	it := v.Interface()
   134  	x, ok := it.(Zeroer)
   135  	if ok {
   136  		return x.IsZero()
   137  	}
   138  
   139  	switch v.Kind() {
   140  	case reflect.Interface, reflect.Func:
   141  		return v.IsNil()
   142  	case reflect.Slice, reflect.Map:
   143  		return v.IsNil() || v.Len() == 0
   144  	case reflect.Array:
   145  		if v.Len() == 0 {
   146  			return true
   147  		}
   148  		z := true
   149  		for i := 0; i < v.Len(); i++ {
   150  			z = z && IsZero(v.Index(i))
   151  		}
   152  		return z
   153  	case reflect.Struct:
   154  		z := true
   155  		for i := 0; i < v.NumField(); i++ {
   156  			z = z && IsZero(v.Field(i))
   157  		}
   158  		return z
   159  	}
   160  
   161  	// Compare other types directly:
   162  	z := reflect.Zero(v.Type())
   163  	return it == z.Interface()
   164  }
   165  
   166  // Set :
   167  func Set(src, v reflect.Value) {
   168  	IndirectInit(src).Set(v)
   169  }