繁体   English   中英

在 Go 中使用反射设置嵌套结构字段的值

[英]Setting values of nested struct fields using reflection in Go

我正在尝试创建一个 protobuf 结构

type FlatMessage map[string][]byte

我正在努力设置嵌套字段的值。

我有一个

func (fm *FlatMessage) Unflatten() (pb.Message, error)

将平面消息转换为结构化 protobuf 的方法。

我还有一个名为analyze的辅助函数,它采用pb.Message类型的结构并返回一个map[int]*ProtoField ,其中:

type ProtoField struct {
    Name  string
    Type  reflect.Type
}

analyze递归遍历pb.Message并收集我需要的所有信息。 到现在为止还挺好。

现在,当我通过FlatMessage逐个键地进行时,键是相应 protobuf 字段的编码字段编号,我可以使用反射来设置它,如下所示:

r := reflect.ValueOf(&result).Elem().FieldByName(field.Name)
if r.IsValid() {
    r.Set(scalarValue)
}

但这仅field.Name于有问题的field.Name不引用嵌套字段时,即设置OldV1Id工作正常,但尝试设置Profile.Id或,例如, Destination.Address.TypeOfNumber ,结果:

panic: reflect: call of reflect.Value.Set on zero Value [recovered]
    panic: reflect: call of reflect.Value.Set on zero Value

我知道这是因为我的r在嵌套字段上调用时变为<invalid Value> ,但我该如何解决它?

我的r当然valid ,不可寻址,不可设置。 我可以制作一个reflect.New ,但我不知道如何设置新的reflect.Value以修改我原始结构的字段。 无论我做什么,我的函数都不会使用这种方法修改具有嵌套名称的字段。

我尝试的另一个解决方案是向我的ProtoField结构添加一个 Value reflect.Value,并修改analyze以便它附加一个reflect.ValueOf(s).Field(i)其中s是顶级结构interface{}i是它的第 i 个字段。 然后,每当我遇到一个嵌套字段时,我都会调用r := reflect.ValueOf(field.Value) ,但问题是由于类型不兼容,我无法调用r.Set(scalarValue)

非常感谢任何帮助或见解。

问题解决了。 ThunderCat在他的评论中是正确的:诀窍是使用FieldByIndex 我之前没有注意到那个方法的签名,我以为它接受一个整数作为参数,但实际上它需要一个整数切片 然后很容易修改我的analyze函数,该函数以递归方式遍历结构,现在还可以在运行时构建一个索引切片。 现在我可以r := reflect.ValueOf(&result).Elem().FieldByIndex(field.Idx)并且我在笑。

这里学到的教训:如果您想使用反射设置嵌套struct字段的值,请不要按名称调用它们; 通过索引调用它们。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM