我正在尝试用一个
创建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
不引用嵌套字段(即设置OldV1Id
可以正常工作,但尝试设置Profile.Id
或{{ 1}},结果为:
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
,使其附加一个analyze
,其中reflect.ValueOf(s).Field(i)
是顶层结构s
,而interface{}
是它的第一个字段。然后,每当遇到嵌套字段时,我都会调用i
,但是问题是由于类型不兼容,我无法调用r := reflect.ValueOf(field.Value)
。
非常感谢您的帮助或见解。
答案 0 :(得分:0)
问题解决了。 ThunderCat在他的评论中是对的:诀窍是使用FieldByIndex
。我之前没有注意到该方法的签名,我认为它接受整数作为参数,但实际上它需要整数的 slice 。然后,很容易修改我的analyze
函数,该函数以递归方式遍历该结构,现在还随其构造一个索引切片。现在我可以r := reflect.ValueOf(&result).Elem().FieldByIndex(field.Idx)
了,我在笑。
经验教训在这里:如果要使用反射设置嵌套struct
字段的值,请不要按名称调用它们;按索引称呼他们。