protobuf 全称: Protocol Buffers, 是Google公司开发的一种数据类型和结构描述语言。是一种数据传输格式,网络数据传输数据,可用 json,也可用 protobuf。
protobuf 很适合做数据存储或 RPC 数据交换格式,它序列化出来的数据量少再加上以 K-V 的方式来存储数据,对消息的版本兼容性非常强,可用于通讯协议、数据存储等领域的 语言无关、平台无关、可扩展的序列化结构数据格式。
开发者可以通过Protobuf附带的工具,生成代码并实现将结构化数据序列化的功能。
protoc 命令,用来把后缀为 .proto 的文件(文件为不同编程语言通用的protobuf数据格式定义文件),编译成特定语言(C++, C#, Dart, Go, Java, Kotlin, Python, Objective-C, PHP, Ruby)的源文件(如.c, .go, .php, .py)。使得特定的编程语言可以直接调用,以解码或编码 protobuf 数据格式.
下载 protoc 命令工具 https://github.com/protocolbuffers/protobuf/releases
复制可执行文件到 环境变量目录. 如 $GOPATH/bin 目录
前面提到,我们可以用 protoc 命令来编译 .proto 文件为特定语言的源文件。
为了支持编译为 go语言,需要安装 protoc-gen-go 插件.
使用 go install 命令下载 protoc-gen-go 插件:
- go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
-
如此,在 $GOPATH/bin 下可见 protoc-gen-go.exe(linux) 或 protoc-gen-go.exe(windows) 文件.
后面执行 protoc 命令会自动调用 protoc-gen-go 插件
- message User {
- string username = 1;
- int32 age = 2;
- optional string password = 3;
- repeated string address = 4;
- }
-
proto | Go | Python | C++ |
---|---|---|---|
double | float64 | float | double |
float | float32 | float | float |
bytes | []byte | str | string |
string | string | str/unicode | string |
protobuf3 删除了 protobuf2 中用来设置默认值的 default 关键字,取而代之的是protobuf3为各类型定义的默认值,也就是约定的默认值,如下表所示:
在消息体的定义中,每个字段都必须要有一个唯一的标识号,标识号是[0,2^29-1]范围内的一个整数。
- message Person {
-
- string name = 1; // (位置1)
- int32 id = 2;
- optional string email = 3;
- repeated string phones = 4; // (位置4)
- }
-
- message PersonInfo {
- message Person {
- string name = 1;
- int32 height = 2;
- repeated int32 weight = 3;
- }
- repeated Person info = 1;
- }
-
- message PersonMessage {
- PersonInfo.Person info = 1;
- }
-
-
创建目录 testProto, 进入该目录,使用命令 go mod init testProto 初始化测试项目
在测试项目中,创建 protos 目录,在其中创建 .proto文件
vim user.proto:
- // 指定的当前proto语法的版本,有2和3
- syntax = "proto3";
- //option go_package = "path;name"; ath 表示生成的go文件的存放地址,会自动生成目录的
- // name 表示生成的go文件所属的包名
- option go_package="../service";
- // 指定等会文件生成出来的package
- package service;
-
- message User {
- string username = 1;
- int32 age = 2;
- }
-
在测试项目中,创建 service 目录,并执行命令生成go版本的protoc源码文件
- # 编译user.proto之后输出到service文件夹
- protoc --go_out=service protos/user.proto
-
以上命令在 service目录 生成 user.pb.go 文件
测试项目中,编写 main.go文件,如下所示:
- package main
-
- import (
- "fmt"
- "google.golang.org/protobuf/proto"
- "testProto/service"
- )
-
- func main() {
- user := &service.User{
- Username: "mszlu",
- Age: 20,
- }
- //转换为protobuf
- marshal, err := proto.Marshal(user)
- if err != nil {
- panic(err)
- }
- newUser := &service.User{}
- err = proto.Unmarshal(marshal, newUser)
- if err != nil {
- panic(err)
- }
- fmt.Println(newUser.String())
- }
-
运行命令:
- # 解决包依赖
- go mod tidy
- # 运行
- go run .
- # 输出
- username:"mszlu" age:20
-
测试项目结构如下:
- ├── go.mod
- ├── go.sum
- ├── main.go
- ├── protos
- │ └── user.proto
- └── service
- └── user.pb.go
-
gRPC官方文档 https://grpc.io/docs/languages/go/quickstart/