我有一个文件,其中包含以下protomessage的一部分字节。
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来使用上面的消息描述符来解析文件的内容。
谢谢您的帮助。
答案 0 :(得分:2)
典型的方法是使用protoc
编译协议以编写Go代码:
protoc main.proto --go_out=.
这将生成main.pb.go
,其类型为Address
:
var addr Address
err := proto.Unmarshal(bytes, &addr)
如果由于某种原因这不可行(例如,您必须使用描述符动态地执行此操作),则有一些选择。 (但这要复杂得多。)
protoc
生成的描述符。您可以将protoc
导出到描述符文件(通过-o
标志)。如果这是用于RPC,请让服务器使用server reflection;然后,您可以使用github.com/jhump/protoreflect/grpcreflect软件包下载服务器的描述符(大概由protoc
生成)。protoc
,建议您使用github.com/jhump/protoreflect/desc/builder包进行构造(而不是尝试手动创建原始原型) )。例如,您的原始原型是不够的,因为它们没有父FileDescriptorProto
,父desc.Descriptor
是任何描述符层次结构的根。该构建器包可以为您处理类似的细节(例如,如有必要,它将合成父文件描述符)。无论如何,所需的描述符是desc.Descriptor
(来自github.com/jhump/protoreflect/desc包)。上面的技巧(使用其他protoreflect子程序包)将返回*descriptor.FileDescriptorProto
个实例。如果只有原始描述符原型(如示例代码中所示),则希望首先使用desc#CreateFileDescriptor函数将*desc.FileDescriptor
变成protoc
。
如果您使用-o
及其--include_imports
选项创建描述符集文件(也不要忘记*desc.FileDescriptor
标志),则可以加载它并将其转换为使用desc#CreateFileDescriptorFromSet函数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`
。这是一个示例:
proto#Unmarshal
一旦有了正确的描述符,就可以创建*dynamic.Message。然后,您可以使用Unmarshal
函数或动态消息的Sub ffs()
Dim wbkS As Workbook
Dim wshS As Worksheet
Dim wshT As Worksheet
Dim strFile As String
With Application.FileDialog(1) ' msoFileDialogOpen
.Filters.Clear
.Filters.Add "Excel workbooks", "*.xls;*.xlsx;*.xlsb;*.xlsm"
.InitialFileName = "D:\Macro testing area"
If .Show Then
strFile = .SelectedItems(1)
Else
MsgBox "No file selected", vbCritical
Exit Sub
End If
End With
Application.ScreenUpdating = False
Set wshT = ActiveSheet
Set wbkS = Workbooks.Open(Filename:=strFile, ReadOnly:=True)
Set wshS = wbkS.Worksheets("Data")
Set wshS1 = wbkS.Worksheets("Section 1")
wshT.Range("A1:L88").Value = wshS.Range("A1:L88").Value
' Optional: close source workbook
wbkS.Close SaveChanges:=False
Application.ScreenUpdating = True
End Sub
方法将其编组。