Source file
src/reflect/visiblefields.go
1
2
3
4
5 package reflect
6
7
8
9
10
11
12
13
14
15
16 func VisibleFields(t Type) []StructField {
17 if t == nil {
18 panic("reflect: VisibleFields(nil)")
19 }
20 if t.Kind() != Struct {
21 panic("reflect.VisibleFields of non-struct type")
22 }
23 w := &visibleFieldsWalker{
24 byName: make(map[string]int),
25 visiting: make(map[Type]bool),
26 fields: make([]StructField, 0, t.NumField()),
27 index: make([]int, 0, 2),
28 }
29 w.walk(t)
30
31
32
33 j := 0
34 for i := range w.fields {
35 f := &w.fields[i]
36 if f.Name == "" {
37 continue
38 }
39 if i != j {
40
41
42 w.fields[j] = *f
43 }
44 j++
45 }
46 return w.fields[:j]
47 }
48
49 type visibleFieldsWalker struct {
50 byName map[string]int
51 visiting map[Type]bool
52 fields []StructField
53 index []int
54 }
55
56
57
58
59
60
61 func (w *visibleFieldsWalker) walk(t Type) {
62 if w.visiting[t] {
63 return
64 }
65 w.visiting[t] = true
66 for i := 0; i < t.NumField(); i++ {
67 f := t.Field(i)
68 w.index = append(w.index, i)
69 add := true
70 if oldIndex, ok := w.byName[f.Name]; ok {
71 old := &w.fields[oldIndex]
72 if len(w.index) == len(old.Index) {
73
74
75
76
77 old.Name = ""
78 add = false
79 } else if len(w.index) < len(old.Index) {
80
81 old.Name = ""
82 } else {
83
84 add = false
85 }
86 }
87 if add {
88
89
90 f.Index = append([]int(nil), w.index...)
91 w.byName[f.Name] = len(w.fields)
92 w.fields = append(w.fields, f)
93 }
94 if f.Anonymous {
95 if f.Type.Kind() == Pointer {
96 f.Type = f.Type.Elem()
97 }
98 if f.Type.Kind() == Struct {
99 w.walk(f.Type)
100 }
101 }
102 w.index = w.index[:len(w.index)-1]
103 }
104 delete(w.visiting, t)
105 }
106
View as plain text