1 回答
TA贡献1777条经验 获得超3个赞
典型的方法是使用以下命令将协议编译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包来构造它(而不是尝试手动创建原始原型)。例如,您的原始原型是不够的,因为它们没有parentFileDescriptorProto
,它是任何描述符层次结构的根。该构建器包可以为您处理类似的细节(例如,如果需要,它将合成父文件描述符)。
无论如何,您想要的描述符是 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.FileDescriptor
bytes, err := ioutil.ReadFile("protoset-from-protoc")
if err != nil {
panic(err)
}
var fileSet descriptor.FileDescriptorSet
if 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方法对其进行解组。
- 1 回答
- 0 关注
- 171 浏览
添加回答
举报