-
Notifications
You must be signed in to change notification settings - Fork 3
/
reflect.go
47 lines (41 loc) · 1.21 KB
/
reflect.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
package reflectKit
import (
"github.com/richelieu-yang/chimera/v3/src/core/errorKit"
"reflect"
"unsafe"
)
// GetNestedField 获取(层层嵌套的)字段
func GetNestedField(ptr interface{}, fieldNames ...string) (reflect.Value, error) {
if fieldNames == nil {
return reflect.Value{}, errorKit.Newf("fieldNames == nil")
}
v := reflect.ValueOf(ptr).Elem()
for i, name := range fieldNames {
if i > 0 {
/*
参考: https://www.codenong.com/50098624/
以避免: panic: reflect: call of reflect.Value.FieldByName on ptr Value
*/
v = reflect.Indirect(v)
}
v = v.FieldByName(name)
}
return v, nil
}
// SetField 设置字段的值.
/*
PS: 支持设置 未导出字段 的值.
@param fieldName 字段名(属性名),private或public的都可以
@param newFieldValue 字段的新值
*/
func SetField(ptr interface{}, fieldName string, newFieldValue interface{}) error {
v := GetField(ptr, fieldName)
// 获取字段的可寻址反射对象(可set)
v = reflect.NewAt(v.Type(), unsafe.Pointer(v.UnsafeAddr())).Elem()
v1 := reflect.ValueOf(newFieldValue)
if v.Kind() != v1.Kind() {
return errorKit.Newf("expected kind %v, got kind: %v", v.Kind(), v1.Kind())
}
v.Set(v1)
return nil
}