Golang 语言 gRPC 使用的接口设计语言 protobuf

2021-09-08 10:58:43 浏览数 (1)

01

介绍

在学习 gRPC 之前,我们需要先了解 Protocal Buffers,也就是 protobuf,它是接口设计语言(IDL),它与编程语言无关,可以生成所有主流编程语言的代码,而且,它是二进制格式的数据,比较适合传递大量的数据。

在编写 gRPC 代码之前,首先使用 protobuf 定义服务端和客户端之间传递的消息(message)和 gRPC 服务(service),然后安装需要用到的库,使用命令行工具自动生成 gRPC 的代码。

02

protobuf 语法

protobuf 文件是以 .proto 后缀名结尾,一般会在文件开头声明 proto 的版本,syntax = "proto3";,如果不声明,则默认使用 proto2 版本。

接下来,我们就可以开始定义消息(message),使用关键字 messagemessage User {},然后在大括号中定义字段。

示例代码:

代码语言:javascript复制
message User {
  int64 id = 1;
  string name = 2;
}

阅读上面这段代码,我们发现定义字段的格式是数据类型,字段名和编号(tag),tag 可以使用的数字范围是 1~536,870,911,但是不能使用 19000~19999 之间的数字,这部分数字是保留编号。

另外,编号 1~15 占用 1 个字节,所以建议用在使用频繁的字段上,编号 16~2047 占用 2 个字节,建议用在使用不频繁的字段上。

03

protobuf 数据类型

protobuf 数据类型包含标量类型和复合类型,其中标量类型包含以下几种:

  • 数值,包含 doublefloatint32int64uint32uint64sint32sint64fixed32fixed64sfixed32sfixed64
  • 布尔 bool
  • 字符串 string
  • 字节 bytes

04

protobuf 字段规则

protobuf 字段规则有两个,单数(singular)和复数(repeated),必须满足其中一个,proto3 默认字段规则是单数。单数的意思是该字段只能出现 0 或 1 次,也可以理解为可选字段,如果出现 0 次,该字段的值是类型零值;复数是包含该字段类型任意数量元素的数组,在 Golang 中是该字段类型的切片。

示例代码:

代码语言:javascript复制
message User {
  int64 id = 1;
  string name = 2;
  repeated string emails = 3;
}

05

protobuf 字段变更

在应用程序开发中,可能会遇到字段修改或删除,protobuf 不允许修改字段的编号(tag),但是可以删除字段,前提是被删除的字段的编号不再被其他字段使用,一般有两种方式,一种是在需要删除的字段名前添加前缀 OBSOLETE_,而不是删除该字段;另一种方式是把需要删除的字段的编号(tag)使用关键字 reserved 保留,避免被其他字段使用被删除字段的编号(tag)。

关键字 reserved 除了可以保留字段编号之外,还可以保留字段名称,可用于设置禁用字段名。

示例代码:

代码语言:javascript复制
message User {
  int64 id = 1;
  string name = 2;
  // repeated string emails = 3;
  reserved 3, 16 to 100, 200 to max;
  reserved "uid", "uname";
}

06

protobuf 定义包名

在应用程序开发中,多个 proto 文件可能会存在相同的消息(message),我们可以使用包名做区分。

示例代码:

代码语言:javascript复制
// 定义包名
package user;
// 定义 golang 包名
option go_package = "userpb";

07

protobuf 嵌套和导入

如果定义的 message 包含一些可以复用的字段,我们可以使用嵌套的方式,将可被复用的字段单独定义为 message,然后嵌套在需要使用它的 message 中,而且,还可以将可被复用的字段在单独的一个文件中定义 message,然后使用关键字 import 导入该文件。

示例代码:

代码语言:javascript复制
// 导入
import "enum.proto";

message User {
  int64 id = 1;
  string name = 2;
  Gender gender = 4;
}

08

protoc 编译器

我们需要安装 protoc 编译器,编译我们编写的 proto 文件,生成指定编程语言的代码。

protoc 命令选项:

代码语言:javascript复制
# 指定 proto 文件的目录
-IPATH, --proto_path=PATH
# 指定 go 文件输出目录
--go_out=dir_name

使用 protoc 编译 proto 文件,生成 golang 代码,需要安装一个包,go get -u github.com/golang/protobuf/protoc-gen-go

示例代码:

代码语言:javascript复制
protoc --proto_path dir_name/ --go_out=dir_name/ dir_name/xx.proto

09

总结

本文我们介绍 gRPC 使用的接口设计语言 protobuf,需要注意的是 proto 文件中字段的编号必须保证唯一,使用 protoc 编译器编译 proto 文件生成指定编程语言的代码,protoc 原生不支持生成 golang 代码,需要安装一个包。

protoc 编译 proto 文件生成的指定编程语言的代码不可以直接修改,如果需要修改,可以修改 proto 文件,然后使用 protoc 重新编译。

限于篇幅,本文无法介绍 protobuf 的全部内容,关于 protobuf 的更多内容,比如枚举,map 等,建议感兴趣的读者朋友们阅读官方文档。

0 人点赞