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

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

介绍

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

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

protobuf 语法

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

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

示例代码:

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 中是该字段类型的切片。

示例代码:

message User {
  int64 id = 1;
  string name = 2;
  repeated string emails = 3;
}

05

protobuf 字段变更

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

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

示例代码:

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),我们可以使用包名做区分。

示例代码:

// 定义包名
package user;
// 定义 golang 包名
option go_package = "userpb";

07

protobuf 嵌套和导入

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

示例代码:

// 导入
import "enum.proto";
message User {
  int64 id = 1;
  string name = 2;
  Gender gender = 4;
}

08

protoc 编译器

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

protoc 命令选项:

# 指定 proto 文件的目录
-IPATH, --proto_path=PATH
# 指定 go 文件输出目录
--go_out=dir_name

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

示例代码:

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 等,建议感兴趣的读者朋友们阅读官方文档。

推荐阅读:

gRPC 初探与简单使用

Go 语言中的 gRPC 基础入门

参考资料:

https://developers.google.com/protocol-buffers/docs/proto3


目录
打赏
0
0
0
0
8
分享
相关文章
|
6月前
|
Go
Golang语言之管道channel快速入门篇
这篇文章是关于Go语言中管道(channel)的快速入门教程,涵盖了管道的基本使用、有缓冲和无缓冲管道的区别、管道的关闭、遍历、协程和管道的协同工作、单向通道的使用以及select多路复用的详细案例和解释。
194 4
Golang语言之管道channel快速入门篇
|
6月前
|
Go
Golang语言文件操作快速入门篇
这篇文章是关于Go语言文件操作快速入门的教程,涵盖了文件的读取、写入、复制操作以及使用标准库中的ioutil、bufio、os等包进行文件操作的详细案例。
94 4
Golang语言文件操作快速入门篇
|
6月前
|
Go
Golang语言之gRPC程序设计示例
这篇文章是关于Golang语言使用gRPC进行程序设计的详细教程,涵盖了RPC协议的介绍、gRPC环境的搭建、Protocol Buffers的使用、gRPC服务的编写和通信示例。
163 3
Golang语言之gRPC程序设计示例
|
6月前
|
Golang语言goroutine协程并发安全及锁机制
这篇文章是关于Go语言中多协程操作同一数据问题、互斥锁Mutex和读写互斥锁RWMutex的详细介绍及使用案例,涵盖了如何使用这些同步原语来解决并发访问共享资源时的数据安全问题。
123 4
|
6月前
|
Golang语言goroutine协程篇
这篇文章是关于Go语言goroutine协程的详细教程,涵盖了并发编程的常见术语、goroutine的创建和调度、使用sync.WaitGroup控制协程退出以及如何通过GOMAXPROCS设置程序并发时占用的CPU逻辑核心数。
185 4
Golang语言goroutine协程篇
Golang语言之Prometheus的日志模块使用案例
这篇文章是关于如何在Golang语言项目中使用Prometheus的日志模块的案例,包括源代码编写、编译和测试步骤。
111 3
Golang语言之Prometheus的日志模块使用案例
实践Golang语言N层应用架构
【10月更文挑战第2天】本文介绍了如何在Go语言中使用Gin框架实现N层体系结构,借鉴了J2EE平台的多层分布式应用程序模型。文章首先概述了N层体系结构的基本概念,接着详细列出了Go语言中对应的构件名称,包括前端框架(如Vue.js、React)、Gin的处理函数和中间件、依赖注入和配置管理、会话管理和ORM库(如gorm或ent)。最后,提供了具体的代码示例,展示了如何实现HTTP请求处理、会话管理和数据库操作。
75 0
Golang语言结构体链式编程与JSON序列化
这篇文章是关于Go语言中结构体链式编程与JSON序列化的教程,详细介绍了JSON格式的基本概念、结构体的序列化与反序列化、结构体标签的使用以及如何实现链式编程。
72 4
|
6月前
|
Go
Golang语言结构体(struct)面向对象编程进阶篇(封装,继承和多态)
这篇文章是关于Go语言中结构体(struct)面向对象编程进阶篇的教程,涵盖了Go语言如何实现封装、继承和多态,以及结构体内存布局的相关概念和案例。
247 4
|
6月前
|
Go
Golang语言基础之接口(interface)及类型断言
这篇文章是关于Go语言中接口(interface)及类型断言的详细教程,涵盖了接口的概念、定义、实现、使用注意事项以及类型断言的多种场景和方法。
69 4