-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreflect.go
More file actions
229 lines (206 loc) · 4.8 KB
/
reflect.go
File metadata and controls
229 lines (206 loc) · 4.8 KB
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
package goreflect
import (
"reflect"
gostrings "github.com/ralvarezdev/go-strings"
)
type (
// Reflection struct to hold reflection data
Reflection struct {
instance any
reflectedValue reflect.Value
reflectedType reflect.Type
reflectedTypeName string
}
)
// GetValue returns the value reflection
//
// Parameters:
//
// - instance: the instance to reflect
//
// Returns:
//
// - reflect.Value: the value reflection
func GetValue(instance any) reflect.Value {
// Check if the instance is nil
if instance == nil {
return reflect.Value{}
}
return reflect.ValueOf(instance)
}
// GetDereferencedValue returns the dereferenced value reflection
//
// Parameters:
//
// - instance: the instance to reflect
//
// Returns:
//
// - reflect.Value: the dereferenced value reflection
func GetDereferencedValue(instance any) reflect.Value {
// Reflect data
valueReflection := GetValue(instance)
// If data is a pointer, dereference it
if valueReflection.Kind() == reflect.Ptr {
valueReflection = valueReflection.Elem()
}
return valueReflection
}
// GetType returns the type reflection
//
// Parameters:
//
// - instance: the instance to reflect
//
// Returns:
//
// - reflect.Type: the type reflection
func GetType(instance any) reflect.Type {
// Check if the instance is nil
if instance == nil {
return nil
}
return reflect.TypeOf(instance)
}
// GetDereferencedType returns the dereferenced type reflection
//
// Parameters:
//
// - instance: the instance to reflect
//
// Returns:
//
// - reflect.Type: the dereferenced type reflection
func GetDereferencedType(instance any) reflect.Type {
// Reflect data
typeReflection := GetType(instance)
// If data is a pointer, dereference it
if typeReflection.Kind() == reflect.Ptr {
typeReflection = typeReflection.Elem()
}
return typeReflection
}
// GetTypeName returns the type name
//
// Parameters:
//
// - typeReflection: the type reflection
//
// Returns:
//
// - string: the type name
func GetTypeName(typeReflection reflect.Type) string {
return typeReflection.Name()
}
// NewReflection creates a new reflection from an instance
//
// Parameters:
//
// - instance: the instance to reflect
//
// Returns:
//
// - *Reflection: the reflection instance
func NewReflection(instance any) *Reflection {
// Reflect data
reflectedValue := GetValue(instance)
reflectedType := GetType(instance)
reflectedTypeName := GetTypeName(reflectedType)
return &Reflection{
instance,
reflectedValue,
reflectedType,
reflectedTypeName,
}
}
// NewDereferencedReflection creates a new reflection from a dereferenced instance
//
// Parameters:
//
// - instance: the instance to reflect
//
// Returns:
//
// - *Reflection: the reflection instance
func NewDereferencedReflection(instance any) *Reflection {
// Reflect data
reflectedValue := GetDereferencedValue(instance)
reflectedType := GetDereferencedType(instance)
reflectedTypeName := GetTypeName(reflectedType)
return &Reflection{
instance,
reflectedValue,
reflectedType,
reflectedTypeName,
}
}
// GetInstance returns the instance
//
// Returns:
//
// - any: the instance
func (r Reflection) GetInstance() any {
return r.instance
}
// GetReflectedValue returns the reflected value
//
// Returns:
//
// - reflect.Value: the reflected value
func (r Reflection) GetReflectedValue() reflect.Value {
return r.reflectedValue
}
// GetReflectedType returns the reflected type
//
// Returns:
//
// - reflect.Type: the reflected type
func (r Reflection) GetReflectedType() reflect.Type {
return r.reflectedType
}
// GetDereferenceReflectedType returns the dereferenced reflected type
//
// Returns:
//
// - reflect.Type: the dereferenced reflected type
func (r Reflection) GetDereferenceReflectedType() reflect.Type {
if r.reflectedType.Kind() == reflect.Ptr {
return r.reflectedType.Elem()
}
return r.reflectedType
}
// GetReflectedTypeName returns the reflected type name
//
// Returns:
//
// - string: the reflected type name
func (r Reflection) GetReflectedTypeName() string {
return r.reflectedTypeName
}
// IsStruct checks if the reflected type is a struct
//
// Returns:
//
// - bool: true if the reflected type is a struct, false otherwise
func (r Reflection) IsStruct() bool {
return r.GetDereferenceReflectedType().Kind() == reflect.Struct
}
// HasField checks if the reflected type has a field with the given name
//
// Parameters:
//
// - fieldName: the field name to check (works for exported fields only)
//
// Returns:
//
// - bool: true if the reflected type has the field, false otherwise
func (r Reflection) HasField(fieldName string) bool {
if !r.IsStruct() {
return false
}
// Convert field name to camel case, because the field must be exported
fieldName = gostrings.ToCamelCase(fieldName)
// Check if the struct has the field
_, found := r.GetDereferenceReflectedType().FieldByName(fieldName)
return found
}