Skip to content

Commit 15b11a8

Browse files
authored
🐛 Fix reflect HasField() with anonymous pointer field. (#736)
Signed-off-by: Jeff Ortel <[email protected]>
1 parent 73a0668 commit 15b11a8

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

reflect/fields.go

+17
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package reflect
22

33
import (
4+
"fmt"
45
"reflect"
56
"time"
67

@@ -92,6 +93,18 @@ func NameOf(m any) (name string) {
9293
// - db.Omit()
9394
// - db.Select()
9495
func HasFields(m any, in ...string) (out []string, err error) {
96+
defer func() {
97+
p := recover()
98+
if p != nil {
99+
if pe, cast := p.(error); cast {
100+
err = pe
101+
} else {
102+
err = fmt.Errorf(
103+
"(paniced) failed: %#v",
104+
p)
105+
}
106+
}
107+
}()
95108
mp := make(map[string]any)
96109
var inspect func(r any)
97110
inspect = func(r any) {
@@ -109,6 +122,10 @@ func HasFields(m any, in ...string) (out []string, err error) {
109122
}
110123
switch fv.Kind() {
111124
case reflect.Ptr:
125+
if ft.Anonymous {
126+
inspect(fv.Interface())
127+
continue
128+
}
112129
inst := fv.Interface()
113130
mp[ft.Name] = inst
114131
case reflect.Struct:

reflect/reflect_test.go

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package reflect
2+
3+
import (
4+
"errors"
5+
"testing"
6+
7+
"github.com/onsi/gomega"
8+
)
9+
10+
func TestHasField(t *testing.T) {
11+
g := gomega.NewGomegaWithT(t)
12+
type B struct {
13+
Name string
14+
Age string
15+
}
16+
type B2 struct {
17+
Name2 string
18+
Age2 string
19+
}
20+
type M struct {
21+
B
22+
*B2
23+
Ptr *B
24+
Object B
25+
Int int
26+
IntPtr *int
27+
List []string
28+
}
29+
30+
// Test expected.
31+
_, err := HasFields(
32+
&M{B2: &B2{}},
33+
"Name",
34+
"Age",
35+
"Name2",
36+
"Age2",
37+
"Ptr",
38+
"Object",
39+
"Int",
40+
"IntPtr",
41+
"List")
42+
g.Expect(err).To(gomega.BeNil())
43+
44+
// Test anonymous NIL pointer.
45+
_, err = HasFields(
46+
&M{}, // PROBLEM HERE.
47+
"Name",
48+
"Age",
49+
"Name2",
50+
"Age2",
51+
"Ptr",
52+
"Object",
53+
"Int",
54+
"IntPtr",
55+
"List")
56+
g.Expect(err).ToNot(gomega.BeNil())
57+
58+
// Invalid field.
59+
_, err = HasFields(
60+
&M{B2: &B2{}},
61+
"Name",
62+
"Age",
63+
"Name2",
64+
"Age2",
65+
"Ptr",
66+
"NOT-VALID", // PROBLEM HERE
67+
"Object",
68+
"Int",
69+
"IntPtr",
70+
"List")
71+
g.Expect(errors.Is(err, &FieldNotValid{})).To(gomega.BeTrue())
72+
}

0 commit comments

Comments
 (0)