在检查 IsZero 时使用 reflect panics 按名称获取字段
Getting field by name using reflect panics when checking IsZero
我有一段反射代码试图通过名称获取结构上的字段,然后检查该字段是否存在:
type test struct {
A bool
B bool
}
t := new(test)
metaValue := reflect.ValueOf(t).Elem()
field := metaValue.FieldByName(name)
if field.IsZero() {
glog.Errorf("Field %s was not on the struct", inner)
}
根据 FieldByName
上的文档,如果未找到字段,此函数应 return 为零值。但是,下一行因错误而恐慌:
panic: reflect: call of reflect.Value.IsZero on zero Value
goroutine 268 [running]:
reflect.Value.IsZero({0x0, 0x0, 0x112a974})
reflect/value.go:1475 +0x27f
根据 this GitHub issue,只有当值包含 nil(即无类型)时才会发生这种情况,应该使用 IsValid
代替。为什么会这样?
Value.IsZero()
报告包装值是否是其类型的零值。这与 reflect.Value
本身为零(reflect.Value
的零值是一个结构)不同。
另请注意,代码中的 t
不是结构值,它是指向结构的指针。使用 Value.Elem()
导航到包装的结构值(或者不要从指针开始)。
如果该字段不存在,Value.FieldByName()
returns the zero value of reflect.Value
,不是一个非零reflect.Value
,持有某种类型的零值;如果找不到字段,则没有类型信息。
所以要检查该字段是否不存在,检查 reflect.Value
本身是否为零,方法是将其与 reflect.Value{}
:
进行比较
if field == (reflect.Value{}) {
log.Printf("Field %s was not on the struct", name)
}
正在测试:
type test struct {
A bool
B bool
x bool
}
v := new(test)
metaValue := reflect.ValueOf(v).Elem()
for _, name := range []string{"A", "x", "y"} {
field := metaValue.FieldByName(name)
if field == (reflect.Value{}) {
log.Printf("Field %s was not on the struct", name)
}
}
这将输出(在 Go Playground 上尝试):
2009/11/10 23:00:00 Field y was not on the struct
我有一段反射代码试图通过名称获取结构上的字段,然后检查该字段是否存在:
type test struct {
A bool
B bool
}
t := new(test)
metaValue := reflect.ValueOf(t).Elem()
field := metaValue.FieldByName(name)
if field.IsZero() {
glog.Errorf("Field %s was not on the struct", inner)
}
根据 FieldByName
上的文档,如果未找到字段,此函数应 return 为零值。但是,下一行因错误而恐慌:
panic: reflect: call of reflect.Value.IsZero on zero Value
goroutine 268 [running]:
reflect.Value.IsZero({0x0, 0x0, 0x112a974})
reflect/value.go:1475 +0x27f
根据 this GitHub issue,只有当值包含 nil(即无类型)时才会发生这种情况,应该使用 IsValid
代替。为什么会这样?
Value.IsZero()
报告包装值是否是其类型的零值。这与 reflect.Value
本身为零(reflect.Value
的零值是一个结构)不同。
另请注意,代码中的 t
不是结构值,它是指向结构的指针。使用 Value.Elem()
导航到包装的结构值(或者不要从指针开始)。
如果该字段不存在,Value.FieldByName()
returns the zero value of reflect.Value
,不是一个非零reflect.Value
,持有某种类型的零值;如果找不到字段,则没有类型信息。
所以要检查该字段是否不存在,检查 reflect.Value
本身是否为零,方法是将其与 reflect.Value{}
:
if field == (reflect.Value{}) {
log.Printf("Field %s was not on the struct", name)
}
正在测试:
type test struct {
A bool
B bool
x bool
}
v := new(test)
metaValue := reflect.ValueOf(v).Elem()
for _, name := range []string{"A", "x", "y"} {
field := metaValue.FieldByName(name)
if field == (reflect.Value{}) {
log.Printf("Field %s was not on the struct", name)
}
}
这将输出(在 Go Playground 上尝试):
2009/11/10 23:00:00 Field y was not on the struct