Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays Go中protobuf数组元素的范围_Arrays_Go_Protocol Buffers_Proto - Fatal编程技术网

Arrays Go中protobuf数组元素的范围

Arrays Go中protobuf数组元素的范围,arrays,go,protocol-buffers,proto,Arrays,Go,Protocol Buffers,Proto,我在.proto文件中定义了一个Protobuf结构: message Msg{ message SubMsg { string SubVariable1 = 1; int32 SubVariable2 = 2; ... } string Variable1 = 1; repeated SubMsg Variable2 = 2; ... } 在使用JSON API中的数据时,我使用包将数据拉入此结构,如下所示: Response, err := Cl

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

message Msg{
  message SubMsg {
    string SubVariable1 = 1;
    int32 SubVariable2 = 2;
    ...
  }
  string Variable1 = 1;
  repeated SubMsg Variable2 = 2;
  ...
}
在使用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访问子变量,为此我尝试了以下两种方法:

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)
尽管事实是
DataProto.GetVariable2()
返回类型为
[]*Msg\u SubMsg
的变量

第二个失败的原因是:

DataProto.GetVariable2.ProtoReflect undefined (type []*SubMsg has no field or method ProtoReflect)
这表明
DataProto.GetVariable2()
确实返回了一个数组,这与我在第一种方法中返回的错误中所建议的不同。这对我来说很有意义,因为protoreflect API只允许对已定义的消息调用此方法,而不允许对这些消息的数组进行调用。因此,必须有另一种方法访问这些数组的元素,才能使用protoreflect API(到目前为止,我在web上还没有找到并回答这个问题)

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


提前感谢。

您需要将
数组
变量视为
列表
,这意味着您不能像第二次尝试那样使用
范围()。不过很接近。下面是迭代和检查嵌套消息的功能示例:


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
        })
    }
}

进口(
“测试”
“google.golang.org/protobuf/reflect/protoreflect”
)
func TestVariable2(t*testing.t){
pb:=&Msg{
变量2:[]*Msg\u SubMsg{
{
子变量1:“字符串”,
子变量2:1,
},
},
}
pbreflect:=pb.ProtoReflect()
fd:=pbreflect.Descriptor().Fields().ByJSONName(“Variable2”)
if!fd.IsList(){
t、 致命(“需要列表”)
}
l:=pbreflect.Get(fd.List())
对于i:=0;i

使用
go test-v./…
运行,如果您想查看输出

是否有令人信服的理由使用
protoreflect
包?
Range
方法用于迭代消息结构的所有字段-它不适用于碰巧是(
重复的
)片段的单个字段。我可能误解了protoreflect Range函数给表带来的内容。考虑到我正在努力迭代一个数组,我认为它将是我的灵丹妙药,因为它提供了访问protoreflect.Value的能力,而调用DataProto.Variable2则不会。即使在没有protoreflect包的情况下接近它(试图覆盖DataProto.Variable2),也会出现同样的错误。您知道我可以迭代未知长度的protobuf数组的方法吗?您似乎在用代码做其他事情。请附上一份。至少,展示一些可以运行的东西,包括生成的protobuf代码。