protobuf在go语言中的应用
1、什么是protobuf?
protocol buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于(数据)通信协议、数据存储等。
Protocol Buffers 是一种灵活,高效,自动化机制的结构数据序列化方法-可类比 XML,但是比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单。
你可以定义数据的结构,然后使用特殊生成的源代码轻松的在各种数据流中使用各种语言进行编写和读取结构数据。你甚至可以更新数据结构,而不破坏由旧数据结构编译的已部署程序。 ——https://developers.google.com/protocol-buffers/
简而言之,protobuf是一种序列化结构数据的方法,类似于XML、JSON,是一种数据传输格式,它的存储方式是二进制,所以有体量更小,解析速度更快的特点。
proto不能像JSON和XML一样开箱即用,需要利用工具(protoc)来编译成常用语言的所能够使用的文件(如果.java,.go等)。
protobuf更像是一个API合同,能够供服务端(Server)和客户端(Client)同时“阅读”的一种API约定、协议。其实它就是协议的一个缓冲文件,缓冲更好地凸显了它的名字中的buf(即buffers)
2、为什么要使用protobuf?
- 易读且容易理解
- 不同语言可以互相操作,因为可以利用工具生成不同语言的代码文件
- 体积小(存储方式是二进制)
- 更快的传输效率(存储方式是二进制)
- 相较于JSON和XML有更高效的序列化能力
- 非常安全(客户端和服务端之间强类型的API合同)
3、支持序列化
序列化的定义:序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。序列化使其他代码可以查看或修改,那些不序列化便无法访问的对象实例数据。
可以把proto文件理解为上述所描述的存储区,可以从proto文件中反序列化出对象的状态,并且创建该对象。
proto相较于普通的序列化强大的一点是,它可以由开发人员按照一定的规范编写文件,并且可以利用protoc反序列化成其他任意语言能够解释的对象。
如果有接触过Java的序列化就能更好理解,Java的序列化会将此时的Java对象的状态序列化到文件当中,但是该文件是不可读的,然后可以利用Java的反序列化将当时的Java对象的状态重建。
4、proto2和proto3
protobuf有两个大版本,proto2和proto3,目前比较新的都是使用proto3,proto3相较于proto2增加了更多语言的支持。
5、protobuf包含什么?
- 业务的描述(service)
- 有效负载消息实体(message)
6、第一次使用protobuf
1、创建新的项目
其中包含两个目录
.
├── go.mod
├── pb #proto编译后的文件
├── proto #proto原始文件
2、创建test.proto文件
确保IDE已经安装了proto相关的插件。
在proto目录下创建
syntax = "proto3";
option go_package = ".;pb";
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
}
3、利用protoc来编译
确保go是1.1版本以上并且能够正常使用go mod
安装能够将proto文件编译成go能够使用的文件的插件protoc-gen-go
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
执行protoc
编译命令
protoc --proto_path=proto proto/*.proto --go_out=pb
可以看到pb目录下已经有了经protoc编译后的文件
.
├── go.mod
├── pb
│ └── test.pb.go
├── proto
│ └── test.proto
4、使用.go文件中的go对象
**OK!**现在已经完成了一次proto文件的编写、以及编译,接下来就可以直接使用.go文件中的go语言能够使用的对象了。
接下来更需要关心的是proto文件的具体编写。
7、编写proto文件
syntax = "proto3";
指定该proto文件的语法是proto3(必须)
option go_package = ".;pb";
指定该proto输出到当前目录下的pb文件夹
message xxx {
// 字段规则:required -> 字段只能也必须出现 1 次
// 字段规则:optional -> 字段可出现 0 次或1次
// 字段规则:repeated -> 字段可出现任意多次(包括 0)
// 类型:int32、int64、sint32、sint64、string、32-bit ....
// 字段编号:0 ~ 536870911(除去 19000 到 19999 之间的数字)
字段规则 类型 名称 = 字段编号;
}
定义消息实体
8、总结
- XML、JSON、Protobuf都具有数据传输的能力
- XML、JSON注重数据结构化,Protobuf注重数据序列化
- Protobuf使用场景更明确,XML、JSON使用场景更丰富且多元(更普遍)。