首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Go中的protobuf数组元素的范围

Go中的protobuf数组元素的范围
EN

Stack Overflow用户
提问于 2020-07-24 20:16:31
回答 1查看 2.1K关注 0票数 2

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

代码语言:javascript
复制
message Msg{
  message SubMsg {
    string SubVariable1 = 1;
    int32 SubVariable2 = 2;
    ...
  }
  string Variable1 = 1;
  repeated SubMsg Variable2 = 2;
  ...
}

在使用来自JSON API的数据时,我使用https://godoc.org/google.golang.org/protobuf/encoding/protojson包将数据拉入到此结构中,如下所示:

代码语言:javascript
复制
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,我已经尝试了这两种方法:

代码语言:javascript
复制
Array := DataProto.GetVariable2()
for i := range Array {
  Element := Array[i]
}

还有:

代码语言:javascript
复制
DataProto.GetVariable2().ProtoReflect().Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) {
      …
      return true})

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

代码语言:javascript
复制
cannot range over DataProto.GetVariable2() (type *SubMsg)

尽管如此,DataProto.GetVariable2()返回一个[]*Msg_SubMsg类型的变量。

第二个失败,出现以下错误:

代码语言:javascript
复制
DataProto.GetVariable2.ProtoReflect undefined (type []*SubMsg has no field or method ProtoReflect)

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

有人能帮我弄明白这些看似矛盾的错误消息吗?有没有人自己成功地迭代过Protobuf数组?

提前谢谢。

EN

回答 1

Stack Overflow用户

发布于 2020-10-07 01:01:50

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

代码语言:javascript
复制
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 ./...运行

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63073384

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档