![](/img/trans.png)
[英]Nested string fields can not be updated using reflection in an arbitrary Go struct
[英]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.