protocol buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法
它可用于(数据)通信协议、数据存储等。
Protocol Buffers 是一种灵活,高效,自动化机制的结构数据序列化方法
可类比 XML,但是比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单。
你可以定义数据的结构,然后使用特殊生成的源代码
轻松的在各种数据流中使用各种语言进行编写和读取结构数据。
你甚至可以更新数据结构,而不破坏由旧数据结构编译的已部署程序。
protobuf通过定义包含类型结构序列化信息的文件(.proto文件),来编译生成不同语言平台的高效序列化程序代码
根据不同系统下载不同protoc编译器,在windows下下载windows后缀的
protoc-3.12.0-rc-1-winxxx.zip
解压后得到的目录中,bin目录中的protoc.exe就是编译protoc代码命令
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2020/5/5 1:24 bin
d----- 2020/5/5 1:24 include
-a---- 2020/5/5 1:24 724 readme.txt
把protoc.exe复制到GOPATH/bin目录下
protobuf编译器有支持golang需要安装protoc-gen-go这个go插件
通过下载源码编译后,把编译出的exe重命名为protoc-gen-go.exe放到GOPATH/bin下
github.com/golang/protobuf
cd protoc-gen-go
go build main.go
在确保有将GOPATH/bin加入环境变量后,即可在任意目录使用protoc命令
protoc --go_out=. --proto_path=. *.proto
其中,go_out指定编译的go代码输出路径,proto_path指定查找proto文件所在的根目录,最后一个参数是要编译的proto文件名
最终旧生成了代码文件xxx.pb.go
如果编译出现警告
Missing 'go_package' option in "test.proto"
这是因为默认.proto文件中的包声明生成源代码时作为Go的包名,包名中的. 在Go包名中会转换为_。
比如proto包名a.b将会变为Go包名a_b,所以一般通过option go_package指令来指定Go包名
比如如下代码指定了go包名为a.b(不管是否定义了proto包名)
option go_package = "a.b";
一般在proto文件开头使用syntax声明proto版本,默认是proto2
比如
syntax = "proto3";
通过import语句导入proto包,比如
import "google/protobuf/struct.proto"
protobuf中使用关键字message定义结构,并且结构中可以嵌套定义结构,比如
message A {}
message B {
message C {
}
}
内嵌类型最终会编译为以外部类型名称_名称作为类型名称的结构体,比如此处,生成的结构体有3个,分别是
type A struct {...}
type B struct {...}
type B_C struct {...}
基本定义语法如下,其中type是类型,name是字段名称,num是数据编号
当反序列化时,会把对应数据编号对应的数据填充到对应字段
对于type,如果是message类型,在编译为语言代码时会被转化为对应的指针类型
type name = num
message A {
string name = 1;
}
message B {
string name = 1;
}
message A {
B b = 1;
}
message A {
map pic = 1;
}
message A{
enum Color{
RED = 0;
BLACK = 1;
}
Color c = 1;
}
enum Day{
ONE = 0;
TWO = 1;
}
message B{}
message A{
repeated B bs= 1;
}
最终生成type B struct {...}
type A struct {
...
Bs []*B ...
}
proto支持通过service与rpc关键字分别定义rpc服务和rpc方法,proto默认不会生成rpc代码,需要结合对应的rpc插件(grpc、twirp等)编译才会生成
比如如下代码,定义了一个service,提供一个search的rpc调用方法,接收一个Request类型的参数,返回Response类型的结果
message Request{}
message Response{}
service Search{
rpc search(Request) returns(Response);
}
google.golang.org/protobuf/
google.golang.org/protobuf/proto
//A is message
a := A{}
bis, _ := proto.Marshal(&a)
fmt.Printf("%v\n", bis)
var r A
proto.Unmarshal(bis, &r)
fmt.Printf("%v\n", r)
更多文章,请搜索公众号歪歪梯Club