/
unknown.go
122 lines (110 loc) · 3.21 KB
/
unknown.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
package pluginloader
import (
"encoding/json"
"errors"
"reflect"
)
//UnknownObject field 'V' MUST be valueof object type *struct{...}
//成员'V' 必须是结构体指针的 Value: *struct{...}
type UnknownObject struct {
V reflect.Value
}
//NewUnknownObject parameter 'v' MUST be valueof object type *struct{...}, or it will return nil
//参数'v' 必须是结构体指针的 Value: *struct{...}, 否则返回 nil
func NewUnknownObject(v reflect.Value) *UnknownObject {
if v.Type().Kind() != reflect.Ptr {
return nil
}
if v.Type().Elem().Kind() != reflect.Struct {
return nil
}
return &UnknownObject{v}
}
//NewUnknownObjectFromInterface parameter 'p' MUST be pointer of struct type, or it will return nil
//参数'p' 必须是结构体指针, 否则返回 nil
func NewUnknownObjectFromInterface(p interface{}) *UnknownObject {
v := reflect.ValueOf(p)
if v.Type().Kind() != reflect.Ptr {
return nil
}
if v.Type().Elem().Kind() != reflect.Struct {
return nil
}
return &UnknownObject{v}
}
//Get 得到结构体成员的 Value
//get the value of a field
func (s *UnknownObject) Get(name string) reflect.Value {
return s.V.Elem().FieldByName(name)
}
//Call 运行结构体的 method
//call the method of the struct
func (s *UnknownObject) Call(fn string, args ...interface{}) []reflect.Value {
f := s.V.MethodByName(fn)
argn := len(args)
argv := make([]reflect.Value, argn)
for i := 0; i < argn; i++ {
if args[i] == nil {
argv[i] = reflect.Zero(f.Type().In(i))
} else {
argv[i] = reflect.ValueOf(args[i])
}
}
return f.Call(argv)
}
//Json 把结构体编码为 JSON。 convert the struct to JSON. if error,return nil.
func (s *UnknownObject) Json() []byte {
res, err := json.Marshal(s.V.Interface())
if err != nil {
return nil
}
return res
}
//CopyToStruct 利用 reflect 技术把结构体的可 export 值复制到 v 中,v 必须是相似结构体的指针。 copy the exported value of a struct to v through gob encoding.
func (s *UnknownObject) CopyToStruct(v interface{}) error {
return structCopy(s.V.Interface(), v)
}
func structCopy(src, dst interface{}) error {
srcV, err := srcFilter(src)
if err != nil {
return err
}
dstV, err := dstFilter(dst)
if err != nil {
return err
}
srcKeys := make(map[string]bool)
for i := 0; i < srcV.NumField(); i++ {
srcKeys[srcV.Type().Field(i).Name] = true
}
for i := 0; i < dstV.Elem().NumField(); i++ {
fName := dstV.Elem().Type().Field(i).Name
if _, ok := srcKeys[fName]; ok {
v := srcV.FieldByName(dstV.Elem().Type().Field(i).Name)
if v.CanInterface() {
dstV.Elem().Field(i).Set(v)
}
}
}
return nil
}
func srcFilter(src interface{}) (reflect.Value, error) {
v := reflect.ValueOf(src)
if v.Type().Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() != reflect.Struct {
return reflect.Zero(v.Type()), errors.New("src type error: not a struct or a pointer to struct")
}
return v, nil
}
func dstFilter(src interface{}) (reflect.Value, error) {
v := reflect.ValueOf(src)
if v.Type().Kind() != reflect.Ptr {
return reflect.Zero(v.Type()), errors.New("src type error: not a pointer to struct")
}
if v.Elem().Kind() != reflect.Struct {
return reflect.Zero(v.Type()), errors.New("src type error: not point to struct")
}
return v, nil
}