英文:
Convert protobuf to struct in golang
问题
我想将proto消息转换为结构体。proto消息和结构体的定义如下:
ProtoMessage:
message Person {
string Name = 1;
int64 Age = 2;
string Location = 3;
}
Human Struct:
type human struct {
Name string `protobuf:"Name"`
Age int64 `protobuf:"Age"`
Location string `protobuf:"Location"`
}
目前我看到的唯一选项是使用protojson和json库将proto转换为JSON,然后再将JSON转换为结构体。有人可以推荐其他的转换方式吗?
英文:
I want to convert the proto Message to struct. Definitions of proto Message and struct:
ProtoMessage:
message Person {
string Name = 1;
int64 Age = 2;
string Location = 3;
}
Human Struct:
type human struct {
Name string `protobuf:"Name"`
Age int64 `protobuf:"Age"`
Location string `protobuf:"Location"`
}
Right now I see that the only option is to convert proto to JSON and JSON to struct using protojson and json library. Can someone recommend any other way of conversion?
答案1
得分: 1
protobuf编译器应该可以有效地为您完成这个任务。
从头开始,进行以下准备工作(75705541
是当前的stackoverflow问题编号):
$ mkdir 75705541
$ cd 75705541
$ wget https://github.com/protocolbuffers/protobuf/releases/download/v22.2/protoc-22.2-linux-x86_64.zip
$ unzip protoc-22.2-linux-x86_64.zip
$ PATH="$(pwd)/bin:${PATH}"
$ go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
创建一个本地文件(ex.proto
):
syntax = "proto3";
message Person {
string Name = 1;
int64 Age = 2;
string Location = 3;
}
然后将其编译为Go代码:
$ protoc -I=./ --go_out=./ --go_opt=Mex.proto=this/ex ex.proto
生成的输出文件 this/ex/ex.pb.go
包含了 Person
的定义:
type Person struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"`
Age int64 `protobuf:"varint,2,opt,name=Age,proto3" json:"Age,omitempty"`
Location string `protobuf:"bytes,3,opt,name=Location,proto3" json:"Location,omitempty"`
}
这几乎是您想要的结果。它有一些额外的字段,但这些字段是私有的,所以在生成的 this/ex
包之外是不可见的。
将二进制数据转换为这个结构的过程可以使用类似下面的代码实现(参考:这里):
var data []byte = yourData // 二进制数据的字节流
var person ex.Person
if err := proto.Unmarshal(data, &person); err != nil {
// 处理解码问题,查看 err。
return err
}
// person 现在包含了您想要的数据。
如果您一定要有一个简化版本,您可能需要手动编辑一个。您可以从类似下面的内容开始:
$ cat this/ex/ex.pb.go | sed -n '/^type Person struct {/,/^}/p' | sed -e '/^[\t]\+[a-z].*$/d'
但是您需要编写一个函数,将 this/ex.Person
的每个导出字段复制到您的 Person
定义中。对于像 ex.Person
这样简单的类型,这相对容易,但如果您有一个嵌套的protobuf定义,这将变得复杂起来。
英文:
The protobuf compiler should effectively do this for you.
From scratch, do this prep (the 75705541
number is this present stackoverflow question):
$ mkdir 75705541
$ cd 75705541
$ wget https://github.com/protocolbuffers/protobuf/releases/download/v22.2/protoc-22.2-linux-x86_64.zip
$ unzip protoc-22.2-linux-x86_64.zip
$ PATH="$(pwd)/bin:${PATH}"
$ go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
Create a local file (ex.proto
):
syntax = "proto3";
message Person {
string Name = 1;
int64 Age = 2;
string Location = 3;
}
Then compile it to Go:
$ protoc -I=./ --go_out=./ --go_opt=Mex.proto=this/ex ex.proto
The generated output, this/ex/ex.pb.go
contains this definition for Person
:
type Person struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"`
Age int64 `protobuf:"varint,2,opt,name=Age,proto3" json:"Age,omitempty"`
Location string `protobuf:"bytes,3,opt,name=Location,proto3" json:"Location,omitempty"`
}
which is almost what you want. It has some extra fields, but these are private so they won't be visible outside our generated "this/ex"
package.
Converting from a wire format blob to this structure uses code like this:
var data []byte = yourData // the binary blob of wire format data
var person ex.Person
if err := proto.Unmarshal(data, &person); err != nil {
// handle decode problem, see err.
return err
}
// person now holds the data you want.
If you must have a simple version, you will likely have to hand edit one. You could start with something like this:
$ cat this/ex/ex.pb.go | sed -n '/^type Person struct {/,/^}/p' | sed -e '/^[\t]\+[a-z].*$/d'
but you will need to write a function to import this by copying each of the exported fields from this/ex.Person
to your Person
definition. This is relatively easy for a simple type like ex.Person
, but it will get complicated if you have a nested protobuf definition.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论