-
Notifications
You must be signed in to change notification settings - Fork 0
/
reflect.go
156 lines (135 loc) · 3.63 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
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
package reflect
import (
"errors"
"fmt"
"reflect"
)
// 获取引用类型的原始类型
func OriginalType(typ reflect.Type) reflect.Type {
switch typ.Kind() {
case reflect.Array, reflect.Chan, reflect.Map, reflect.Ptr, reflect.Slice:
return OriginalType(typ.Elem())
}
return typ
}
// TODO:
func ContainType() {
}
// SetSubField 设置字段值
// 参数均为指针,dst类型为src field的类型
func SetSubField(src any, sub any) bool {
srcValue := reflect.ValueOf(src).Elem()
subValue := reflect.ValueOf(sub).Elem()
return SetSubFieldValue(srcValue, subValue)
}
// SetSubFieldValue 设置字段值
// subValue为srcValue field的类型
func SetSubFieldValue(srcValue reflect.Value, subValue reflect.Value) bool {
for i := 0; i < srcValue.NumField(); i++ {
if srcValue.Field(i).Type() == subValue.Type() {
srcValue.Field(i).Set(subValue)
return true
}
}
return false
}
// CopyFieldValueByType 根据类型复制字段
// 参数均为指针,sub类型为src field的类型
func CopyFieldValueByType(src any, sub any) bool {
srcValue := reflect.ValueOf(src).Elem()
dstValue := reflect.ValueOf(sub).Elem()
for i := 0; i < srcValue.NumField(); i++ {
if srcValue.Field(i).Type() == dstValue.Type() {
dstValue.Set(srcValue.Field(i))
return true
}
}
return false
}
func SetField(structValue reflect.Value, name string, value any) error {
fieldValue := structValue.FieldByName(name)
if !fieldValue.IsValid() {
return fmt.Errorf("no such field: %s in obj ", name)
}
if !fieldValue.CanSet() {
return fmt.Errorf("cannot set %s field value ", name)
}
fieldType := fieldValue.Type()
val := reflect.ValueOf(value)
valTypeKind := val.Type().Kind()
fieldTypeKind := fieldType.Kind()
if fieldType != val.Type() && val.CanConvert(fieldType) {
val = val.Convert(fieldType)
} else {
return fmt.Errorf("provided value type %s didn't match obj field type %s", valTypeKind, fieldTypeKind)
}
fieldValue.Set(val)
return nil
}
// Copy 复制结构体,浅表复制
func CopyStruct(src any, dest any) error {
valueOfS := reflect.ValueOf(src)
typeOfT := reflect.TypeOf(dest)
if valueOfS.Kind() == reflect.Ptr {
valueOfS = valueOfS.Elem()
}
if valueOfS.Kind() != reflect.Struct {
return errors.New("src is not a ptr or struct")
}
if typeOfT.Kind() != reflect.Ptr {
return errors.New("dest is not a ptr")
}
typeOfT = typeOfT.Elem()
valueOfT := reflect.ValueOf(dest).Elem()
for i := 0; i < typeOfT.NumField(); i++ {
// 获取每个成员的结构体字段值
fieldType := typeOfT.Field(i)
// 赋值
valueOfT.Field(i).Set(valueOfS.FieldByName(fieldType.Name))
}
return nil
}
func CanCast(t1, t2 reflect.Type, strict bool) bool {
t1kind, t2kind := t1.Kind(), t2.Kind()
if strict {
if t1kind != t2kind {
return false
}
if t1kind <= reflect.Complex128 {
return true
}
} else {
if t1kind == t2kind {
return true
}
if (t1kind == reflect.Complex64 || t1kind == reflect.Complex128) && (t2kind == reflect.Complex64 || t2kind == reflect.Complex128) {
return true
}
}
switch t1kind {
case reflect.String:
return t1kind == t2kind
case reflect.Ptr, reflect.Array, reflect.Chan, reflect.Slice, reflect.Map:
if t1kind == reflect.Map {
if !CanCast(t1.Key(), t2.Key(), true) {
return false
}
}
if t1kind == reflect.Array && t1.Len() != t2.Len() {
return false
}
return CanCast(t1.Elem(), t2.Elem(), true)
case reflect.Struct:
if t1.NumField() != t2.NumField() {
return false
}
for i := 0; i < t1.NumField(); i++ {
if !CanCast(t1.Field(i).Type, t2.Field(i).Type, true) {
return false
}
}
case reflect.Interface, reflect.UnsafePointer:
return t1 == t2
}
return true
}