@@ -81,57 +81,44 @@ func getMethod(value reflect.Value, name string) reflect.Value {
81
81
// and any embedded fields.
82
82
//
83
83
// Returns a slice of bound methods that can be called directly.
84
- func getMethods (value reflect.Value , name string ) []reflect.Value {
85
- // Traverses embedded fields of the struct
86
- // starting from the given value to collect all possible receivers
87
- // for the given method name.
88
- var traverse func (value reflect.Value , receivers []reflect.Value ) []reflect.Value
89
- traverse = func (value reflect.Value , receivers []reflect.Value ) []reflect.Value {
90
- // Always consider the current value for hooks.
91
- receivers = append (receivers , value )
92
-
93
- if value .Kind () == reflect .Ptr {
94
- value = value .Elem ()
95
- }
84
+ func getMethods (value reflect.Value , name string ) (methods []reflect.Value ) {
85
+ if value .Kind () == reflect .Ptr {
86
+ value = value .Elem ()
87
+ }
88
+ if ! value .IsValid () {
89
+ return
90
+ }
96
91
97
- // If the current value is a struct, also consider embedded fields.
98
- // Two kinds of embedded fields are considered if they're exported:
99
- //
100
- // - standard Go embedded fields
101
- // - fields tagged with `embed:""`
102
- if value .Kind () == reflect .Struct {
103
- t := value .Type ()
104
- for i := 0 ; i < value .NumField (); i ++ {
105
- fieldValue := value .Field (i )
106
- field := t .Field (i )
107
-
108
- if ! field .IsExported () {
109
- continue
110
- }
111
-
112
- // Consider a field embedded if it's actually embedded
113
- // or if it's tagged with `embed:""`.
114
- _ , isEmbedded := field .Tag .Lookup ("embed" )
115
- isEmbedded = isEmbedded || field .Anonymous
116
- if isEmbedded {
117
- receivers = traverse (fieldValue , receivers )
118
- }
119
- }
120
- }
92
+ if method := getMethod (value , name ); method .IsValid () {
93
+ methods = append (methods , method )
94
+ }
121
95
122
- return receivers
96
+ if value .Kind () != reflect .Struct {
97
+ return
123
98
}
99
+ // If the current value is a struct, also consider embedded fields.
100
+ // Two kinds of embedded fields are considered if they're exported:
101
+ //
102
+ // - standard Go embedded fields
103
+ // - fields tagged with `embed:""`
104
+ t := value .Type ()
105
+ for i := 0 ; i < value .NumField (); i ++ {
106
+ fieldValue := value .Field (i )
107
+ field := t .Field (i )
124
108
125
- receivers := traverse (value , nil /* receivers */ )
109
+ if ! field .IsExported () {
110
+ continue
111
+ }
126
112
127
- // Search all receivers for methods
128
- var methods []reflect.Value
129
- for _ , receiver := range receivers {
130
- if method := getMethod (receiver , name ); method .IsValid () {
131
- methods = append (methods , method )
113
+ // Consider a field embedded if it's actually embedded
114
+ // or if it's tagged with `embed:""`.
115
+ _ , isEmbedded := field .Tag .Lookup ("embed" )
116
+ isEmbedded = isEmbedded || field .Anonymous
117
+ if isEmbedded {
118
+ methods = append (methods , getMethods (fieldValue , name )... )
132
119
}
133
120
}
134
- return methods
121
+ return
135
122
}
136
123
137
124
func callFunction (f reflect.Value , bindings bindings ) error {
0 commit comments