-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathstruct_tag.go
59 lines (52 loc) · 1.25 KB
/
struct_tag.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
package deepcopy
import (
"reflect"
"strings"
)
// fieldDetail stores field copying detail parsed from a struct field
type fieldDetail struct {
field *reflect.StructField
key string
ignored bool
required bool
nilOnZero bool
done bool
index []int
nestedFields []*fieldDetail
}
// markDone sets the `done` flag of a field detail and all of its nested fields recursively
func (detail *fieldDetail) markDone() {
detail.done = true
for _, f := range detail.nestedFields {
f.markDone()
}
}
// parseTag parses struct tag for getting copying detail and configuration
func parseTag(detail *fieldDetail) {
tagValue, ok := detail.field.Tag.Lookup(defaultTagName)
detail.key = detail.field.Name
if !ok {
return
}
tags := strings.Split(tagValue, ",")
switch {
case tags[0] == "-":
detail.ignored = true
case tags[0] != "":
detail.key = tags[0]
}
for _, tagOpt := range tags[1:] {
switch tagOpt {
case "required":
if !detail.ignored {
detail.required = true
}
case "nilonzero":
k := detail.field.Type.Kind()
// Set nil on zero only applies to types which can set `nil`
if k == reflect.Pointer || k == reflect.Interface || k == reflect.Slice || k == reflect.Map {
detail.nilOnZero = true
}
}
}
}