猿问

如何使用 github.com/jhump/protoreflect 解析知道消息描述符

我有一个文件,其中包含以下原始消息的字节片段。


syntax = "proto3";


package main;


message Address {

    string street = 1;

    string country = 2;

    string state = 3;

}

我的消息类型描述如下:


func GetProtoDescriptor() (*descriptor.DescriptorProto, error) {


    return &descriptor.DescriptorProto{

        Name: proto.String("Address"),

        Field: []*descriptor.FieldDescriptorProto{

            &descriptor.FieldDescriptorProto{

                Name:     proto.String("street"),

                JsonName: proto.String("street"),

                Number:   proto.Int(1),

                Label:    descriptor.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),

                Type:     descriptor.FieldDescriptorProto_TYPE_STRING.Enum(),

            },


            &descriptor.FieldDescriptorProto{

                Name:     proto.String("state"),

                JsonName: proto.String("state"),

                Number:   proto.Int(2),

                Label:    descriptor.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),

                Type:     descriptor.FieldDescriptorProto_TYPE_STRING.Enum(),

            },


            &descriptor.FieldDescriptorProto{

                Name:     proto.String("country"),

                JsonName: proto.String("country"),

                Number:   proto.Int(2),

                Label:    descriptor.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),

                Type:     descriptor.FieldDescriptorProto_TYPE_STRING.Enum(),

            },

        },

    }, nil


}


我想知道如何最好地使用jhump/protoreflect使用上面的消息描述符来解析文件的内容。


感谢您的帮助。


LEATH
浏览 172回答 1
1回答

慕森王

典型的方法是使用以下命令将协议编译protoc为 Go 代码:protoc main.proto --go_out=.这将生成main.pb.go,其类型称为Address:var addr Address err := proto.Unmarshal(bytes, &addr)如果由于某种原因这是不可能的(例如,您必须使用描述符动态地执行此操作),那么还有其他选择。(但情况要复杂得多。)使用protoc生成的描述符。您可以protoc导出到描述符文件(通过-o标志)。如果这是用于 RPC,请让服务器使用服务器反射;然后,您可以使用github.com/jhump/protoreflect/grpcreflect包下载服务器的描述符(大概由 生成protoc)。如果您必须以编程方式创建描述符,而不是使用protoc,我建议使用github.com/jhump/protoreflect/desc/builder包来构造它(而不是尝试手动创建原始原型)。例如,您的原始原型是不够的,因为它们没有parent FileDescriptorProto,它是任何描述符层次结构的根。该构建器包可以为您处理类似的细节(例如,如果需要,它将合成父文件描述符)。无论如何,您想要的描述符是 a desc.Descriptor(来自github.com/jhump/protoreflect/desc包)。上面的提示(使用其他 protoreflect 子包)将返回desc.Descriptor实例。如果您只有原始描述符原型(如示例代码中所示),您需要首先使用desc#CreateFileDescriptor*descriptor.FileDescriptorProto函数将其转换为 a 。*desc.FileDescriptor如果您正在使用protoc及其-o选项来创建描述符集文件(也不要忘记标志),您可以使用desc#CreateFileDescriptorFromSet--include_imports函数加载它并将其转换为描述符集文件。这是一个例子:*desc.FileDescriptorbytes, err := ioutil.ReadFile("protoset-from-protoc")if err != nil {  panic(err)}var fileSet descriptor.FileDescriptorSetif err := proto.Unmarshal(bytes, &fileSet); err != nil {  panic(err)}fd, err := desc.CreateFileDescriptorFromSet(&fileSet)if err != nil {  panic(err)}// Now you have a *desc.FileDescriptor in `fd`一旦有了正确的描述符,您就可以创建一个*dynamic.Message。然后,您可以使用该proto#Unmarshal函数或使用动态消息的Unmarshal方法对其进行解组。
随时随地看视频慕课网APP

相关分类

Go
我要回答