-
Notifications
You must be signed in to change notification settings - Fork 34
/
reflectx.go
138 lines (124 loc) · 2.81 KB
/
reflectx.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package reflectx
import (
"bytes"
"reflect"
)
func Indirect(v reflect.Value) reflect.Value {
if v.Kind() == reflect.Ptr {
return Indirect(v.Elem())
}
return v
}
// New a `reflect.Value` with reflect.Type
func New(t reflect.Type) reflect.Value {
v := reflect.New(t).Elem()
if t.Kind() == reflect.Ptr {
v.Set(New(t.Elem()).Addr())
}
return v
}
func IsEmptyValue(v interface{}) bool {
rv, ok := v.(reflect.Value)
if !ok {
rv = reflect.ValueOf(&v).Elem()
}
if rv.Kind() == reflect.Ptr && rv.IsNil() {
return true
}
if rv.Kind() == reflect.Interface && rv.IsNil() {
return true
}
if rv.Kind() == reflect.Invalid {
return true
}
if rv.IsValid() && rv.CanInterface() {
if chk, ok := rv.Interface().(interface{ IsZero() bool }); ok {
return chk.IsZero()
}
}
switch rv.Kind() {
case reflect.Array, reflect.Slice, reflect.Map, reflect.String:
return rv.Len() == 0
case reflect.Bool:
return !rv.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return rv.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return rv.Uint() == 0
case reflect.Float32, reflect.Float64:
return rv.Float() == 0
case reflect.Ptr, reflect.Interface:
return IsEmptyValue(rv.Elem())
}
return false
}
func TypeName(rt reflect.Type) string {
buf := bytes.NewBuffer(nil)
for rt.Kind() == reflect.Ptr {
buf.WriteByte('*')
rt = rt.Elem()
}
if pkg := rt.PkgPath(); pkg != "" {
buf.WriteString(pkg)
buf.WriteByte('.')
}
if name := rt.Name(); name != "" {
buf.WriteString(name)
}
buf.WriteString(rt.String())
return buf.String()
}
func DeRef(t reflect.Type) reflect.Type {
for t.Kind() == reflect.Ptr {
t = t.Elem()
}
return t
}
// NatureType return the v's nature type, for example:
// Foo nature type is Foo
// *Foo nature type is Foo
// ***Foo nature type is Foo
// reflect.TypeOf(Foo) nature type is Foo
// (interface{})(Foo) nature type is Foo
func NatureType(v interface{}) (rt reflect.Type) {
if !reflect.ValueOf(v).IsValid() {
return reflect.TypeOf(nil)
}
rt = reflect.TypeOf(v)
if t, ok := v.(reflect.Type); ok {
rt = t
}
kind := rt.Kind()
for kind == reflect.Ptr {
rt = rt.Elem()
kind = rt.Kind()
}
if kind == reflect.Interface {
return NatureType(reflect.New(rt).Elem().Interface())
}
return rt
}
func IsBytes(v interface{}) bool {
if _, ok := v.([]byte); ok {
return true
}
t := BasicAssertReflectType(v)
return IsBytesType(t)
}
func IsBytesType(t reflect.Type) bool {
return t.Kind() == reflect.Slice &&
t.Elem().Kind() == reflect.Uint8 &&
t.Elem().PkgPath() == ""
}
func BasicAssertReflectType(v interface{}) reflect.Type {
var t reflect.Type
switch x := v.(type) {
case reflect.Type:
t = x
case interface{ Type() reflect.Type }:
t = x.Type()
default:
t = reflect.TypeOf(v)
}
return t
}