在Go中,在protobuf数组的元素上进行测距



我的.proto文件中定义了一个Protobuf结构:

message Msg{
message SubMsg {
string SubVariable1 = 1;
int32 SubVariable2 = 2;
...
}
string Variable1 = 1;
repeated SubMsg Variable2 = 2;
...
}

我使用https://godoc.org/google.golang.org/protobuf/encoding/protojson使用JSON API数据时的包,如下所示:

Response, err := Client.Do(Request)
if err != nil {
log.Error(err)
}
DataByte, err := ioutil.ReadAll(Response.Body)
if err != nil {
log.Error(err)
}
DataProto := Msg{}
err = protojson.Unmarshal(DataByte, &DataProto)
if err != nil {
log.Error(err)
}

我想做的是覆盖Variable2的元素,以便能够使用protoreflect API访问SubVariables,为此我已经尝试了两种方法:

Array := DataProto.GetVariable2()
for i := range Array {
Element := Array[i]
}

以及:

DataProto.GetVariable2().ProtoReflect().Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) {
…
return true})

第一个失败并显示错误消息:

cannot range over DataProto.GetVariable2() (type *SubMsg)

尽管事实上CCD_ 1返回类型为CCD_。

第二个失败:

DataProto.GetVariable2.ProtoReflect undefined (type []*SubMsg has no field or method ProtoReflect)

这表明CCD_ 3确实返回了一个数组,这与我的第一种方法中返回的错误不同。这对我来说很有意义,因为protoreflect API只允许在定义的消息上调用此方法,而不允许在这些消息的数组上调用。因此,必须有另一种方法来访问这些数组的元素,才能使用protoreflect API(到目前为止,我还没有在网上找到并回答这个问题(。

有人能帮我理解这些看似矛盾的错误信息吗?有没有人自己成功地迭代了Protobuf数组?

提前谢谢。

您需要将Array变量视为List,这意味着您不能像在第二次尝试中那样使用Range()。虽然很接近。下面是一个遍历和检查嵌套消息的功能示例:


import (
"testing"
"google.golang.org/protobuf/reflect/protoreflect"
)
func TestVariable2(t *testing.T) {
pb := &Msg{
Variable2: []*Msg_SubMsg{
{
SubVariable1: "string",
SubVariable2: 1,
},
},
}
pbreflect := pb.ProtoReflect()
fd := pbreflect.Descriptor().Fields().ByJSONName("Variable2")
if !fd.IsList() {
t.Fatal("expected a list")
}
l := pbreflect.Get(fd).List()
for i := 0; i < l.Len(); i++ {
// should test that we are now inspecting a message type
li := l.Get(i).Message()
li.Range(func(lifd protoreflect.FieldDescriptor, liv protoreflect.Value) bool {
t.Logf("%v: %v", lifd.Name(), liv)
return true
})
}
}

如果要查看输出,请使用go test -v ./...运行

最新更新