说明
Protocol Buffers是一个语言中立、平台中立可扩展的用于序列化的结构化数据。
Protocol Buffers优点
- 紧凑的数据压缩存储
- 快速解析
- 多语言编程可用性
- 通过自动生成的类优化功能
Protocol Buffers 局限性
- 大数据集:当处理的数据量超过几兆字节时,Protocol Buffers可能不是最佳选择。因为它们假设整个消息可以一次性加载到内存中,对于大数据集来说,这可能会导致内存使用量的急剧增加,并且在序列化过程中可能会产生数据的多个副本。
- 序列化多样性:Protobuf 序列化后的数据即使对于相同的数据结构也可能有多种不同的二进制表示形式,这意味着你不能直接比较两个序列化消息的等价性,除非先进行反序列化。
- 科学和工程数据
- 非面向对象语言:Protocol Buffers主要设计为与面向对象语言一起使用。
- 自描述性:需要配合.proto文件才能完全解释一个Protobuf消息
- 非正式的标准
协议说明
// proto版本,目前支持2和3,如果不指定,编译器默认为用2
syntax = "proto3";
package tutorial;
import "google/protobuf/timestamp.proto";
//定义数据类型
message Message {
/*
* 字段类型可以是基本数据类型,枚举、或其他自定义的Message类型
* 为字段编号,编号必须唯一。注意:19,000 to 19,999是Protocol Buffers保留字,不能使用
* 编号一旦分配不能改变,对于常用字段可以设置为1-15,进需要1个字节。16-2047需要两个字节,依次类推
* 即使一个字段已经被删除了,这个字段的编号也应被视为保留,这个字段的编号不能被新字段使用。避免出现兼容性问题
* 不同类型字段默认值不一样 */
string id = 1;
string text = 2;
}
option go_package = "goLearning/protocol/protoBuf/pb";
message Person {
string name = 1;
int32 id = 2;
string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
repeated PhoneNumber phones = 4;
google.protobuf.Timestamp last_updated = 5;
}
message AddressBook {
repeated Person people = 1;
}
go使用
1、需要先安装编译器,可以下载预编译好的包
https://github.com/protocolbuffers/protobuf/releases/tag/v27.3
解压之后,可以把protoc.exe配置到系统变量path中。
2、生成go语言代码还需要额外安装插件protoc-gen-go,执行如下命令
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
3、生成go代码
protoc -I=$SRC_DIR --go_out=$DST_DIR $SRC_DIR/addressbook.proto
protoc -I=F:\GolandProjects\goLearning\protocol\protoBuf --go_out=./pb F:\GolandProjects\goLearning\protocol\protoBuf\addressbook.proto
4、读写消息
前面步骤根据proto文件生成了proto message相关的代码。如果需要对proto message进行相关的操作还 需要安装 Protobuf runtime包。不同语言提供了不同的安装方式,如果是Java直接添加maven依赖
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version><!--version--></version>
</dependency>
go的话添加go的 Protocol Buffers runtime
require google.golang.org/protobuf v1.30.0
安装成功后,就可以使用依赖库提供的工具包(部分如下):
- proto:提供对protobuf messages消息的操作方法,合并、克隆、相等判断、二进制序列化
- encoding/protojson、prototext、protowire:提供json/text/wire等的序列化
- reflect:提供反射相关的操作
- types/dynamicpb: 可以在运行时动态创建protobuf消息,非常适合在一些基础框架上,不需要在编译期绑定特定内容,而是动态灵活解析。
- types/known/anypb: 允许构建通用的API消息
protoreflect 是 Go 语言中用于处理 Protocol Buffers 消息的反射 API。它允许开发者在运行时动态地操作 Protobuf 消息,包括访问字段、设置字段值、获取元数据等。
使用场景:
- 动态消息处理:
在某些场景中,你可能需要处理未知的 Protobuf 消息类型,比如构建一个通用的消息处理系统。这时可以使用 protoreflect 动态地解析和操作消息,而无需预先知道消息的结构。
- 消息转换:
当需要在不同版本的 Protobuf 消息之间进行转换,或从一种消息格式转换为另一种消息格式时,protoreflect 可以用来动态读取和设置字段值,从而实现消息的转换。
- 调试和日志记录:
通过 protoreflect,你可以在调试时查看消息的详细信息,如字段名称、类型和值。它也可以用于记录复杂的 Protobuf 消息,以便更好地理解和分析消息内容。
- 自定义序列化:
如果你需要自定义 Protobuf 消息的序列化逻辑(比如实现自定义的序列化格式),protoreflect 提供了对消息内部结构的访问,可以帮助你实现这一功能。
具体例子可以参考官网
https://github.com/protocolbuffers/protobuf/tree/main/examples/go/cmd