为了账号安全,请及时绑定邮箱和手机立即绑定

检查 IsZero 时使用反射恐慌按名称获取字段

检查 IsZero 时使用反射恐慌按名称获取字段

Go
RISEBY 2022-10-10 17:02:56
我有一段反射代码尝试按名称获取结构上的字段,然后检查该字段是否存在: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,如果未找到任何字段,此函数应返回零值。但是,下一行会出现以下错误:panic: reflect: call of reflect.Value.IsZero on zero Valuegoroutine 268 [running]:reflect.Value.IsZero({0x0, 0x0, 0x112a974})        reflect/value.go:1475 +0x27f根据这个 GitHub 问题,只有当值包含 nil (即没有类型)时才会发生这种情况,并且IsValid应该使用它。为什么会这样?
查看完整描述

1 回答

?
神不在的星期二

TA贡献1963条经验 获得超6个赞

Value.IsZero()报告包装的值是否是其类型的零值。这与reflect.Value自身为零(reflect.Value其零值是结构)不同。

另请注意,t在您的代码中不是结构值,它是指向结构的指针。用于Value.Elem()导航到包装的结构值(或不从指针开始)。

如果该字段不存在,Value.FieldByName()则返回 的零值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


查看完整回答
反对 回复 2022-10-10
  • 1 回答
  • 0 关注
  • 56 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信