-
Notifications
You must be signed in to change notification settings - Fork 1
/
copyStruct.go
60 lines (57 loc) · 1.54 KB
/
copyStruct.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
package tools
import (
"reflect"
)
// StructCopy 结构体拷贝
func StructCopy(DstStructPtr interface{}, SrcStructPtr interface{}) {
srcv := reflect.ValueOf(SrcStructPtr)
dstv := reflect.ValueOf(DstStructPtr)
srct := reflect.TypeOf(SrcStructPtr)
dstt := reflect.TypeOf(DstStructPtr)
if srct.Kind() != reflect.Ptr || dstt.Kind() != reflect.Ptr ||
srct.Elem().Kind() == reflect.Ptr || dstt.Elem().Kind() == reflect.Ptr {
panic("Fatal error:type of parameters must be Ptr of value")
}
if srcv.IsNil() || dstv.IsNil() {
panic("Fatal error:value of parameters should not be nil")
}
srcV := srcv.Elem()
dstV := dstv.Elem()
srcfields := deepFields(reflect.ValueOf(SrcStructPtr).Elem().Type())
for _, v := range srcfields {
if v.Anonymous {
continue
}
dst := dstV.FieldByName(v.Name)
src := srcV.FieldByName(v.Name)
if !dst.IsValid() {
continue
}
if src.Type() == dst.Type() && dst.CanSet() {
dst.Set(src)
continue
}
if src.Kind() == reflect.Ptr && !src.IsNil() && src.Type().Elem() == dst.Type() {
dst.Set(src.Elem())
continue
}
if dst.Kind() == reflect.Ptr && dst.Type().Elem() == src.Type() {
dst.Set(reflect.New(src.Type()))
dst.Elem().Set(src)
continue
}
}
return
}
func deepFields(ifaceType reflect.Type) []reflect.StructField {
var fields []reflect.StructField
for i := 0; i < ifaceType.NumField(); i++ {
v := ifaceType.Field(i)
if v.Anonymous && v.Type.Kind() == reflect.Struct {
fields = append(fields, deepFields(v.Type)...)
} else {
fields = append(fields, v)
}
}
return fields
}