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 }