ProtoBuf的安装及在Go中的使用 | 青训营笔记

776 阅读4分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记。

前言 以往的前后端分离项目中,数据通信都是使用的JSON格式进行传递,但是最近接触到了protobuf这一新格式,有着众多优势,值得学习。通过这篇笔记记录一下学习protobuf的安装和基础使用的过程。

1 什么是protobuf

protobuf(Protocol Buffers),是Google公司开发的一种轻便高效的结构化数据存储格式,并且与语言、平台无关,可扩展、可序列化。protobuf 是以二进制方式存储的,占用空间小,性能和效率大幅度优于 JSON、XML 等其他的结构化数据格式,但由于是二进制格式存储的,具有可读性较差的缺点。protobuf 在通信协议和数据存储等领域应用广泛。

2 配置使用环境

想要使用protobuf,需要编写要存储的数据结构的.proto描述。该描述文件需要通过protobuf编译器进行编译,因此我们首先需要下载protoc编译器。

2.1 下载protoc编译器

我们可以在github官方仓库(github.com/protocolbuf…)中找到编译器的安装教程。

image-20220512134733705.png

根据官方文档,我们了解到protoc编译器是使用C++语言编写的。想要安装该编译器,可以通过两种方式:(1)下载项目源码,通过C++编译环境进行源码编译;(2)在release(github.com/protocolbuf…)下载官方提供的预先编译好的版本。第一个方法比较麻烦,可以参考官方文档(github.com/protocolbuf…)自行实践。下面主要描述第二种安装方式:

截至笔记编写时间,最新的发布版本是v3.20.1。由于我使用的是M1 Mac,因此下载该版本protoc-3.20.1-osx-aarch_64.zip。读者可根据自己电脑配置,选择适合的版本进行下载。

image-20220512135932699.png

2.2 配置环境变量

根据2.1的步骤下载得到的是一个zip压缩文件,将其直接解压并放置在合适位置,下一步需要配置环境变量,指向该文件。网络上有关如何在macOS系统中配置环境变量的文章较多,在此不再赘述。我将文件放置在~/下,因此应该修改.zshrc文件,在末尾添加如下内容:

export PATH="$PATH:/Users/eamon/protoc-3.20.1-osx-aarch_64/bin" 

保存并退出后,记得执行如下命令,使配置生效。

source ~/.zshrc

注:使用bash的,可以自行查阅相关资料进行设置。

设置好环境变量以后,我们可以执行如下命令查看protoc版本,验证是否安装成功。

protoc -version

可以看到正常显示了版本,因此安装成功。

image-20220512141110024.png

2.3 安装protoc-gen-go

除了上面编译器的安装,我们还需要安装protoc-gen-go插件才能使编译器编译生成go代码,通过如下命令即可安装:

go install google.golang.org/protobuf/cmd/protoc-gen-go@latest

⚠️避坑指南:

(1)在查阅网上资料时,浏览到的很多文章都会写安装该插件应执行如下命令:

go get -u github.com/golang/protobuf/protoc-gen-go

那你将得到如下报错:

go: module github.com/golang/protobuf is deprecated: Use the "google.golang.org/protobuf" module instead.

错误提示指明该插件已经迁移到了新的地址,而且注意要使用install而不是get,否则无法正确安装。

总之,执行我上面提供的命令即可。此外,记得将$GOPATH/bin加入环境变量,方法同上。

3 定义数据结构

protobuf的数据结构都是通过.proto文件进行定义的,然后使用protoc编译成相应的语言,下面通过一个简单示例来进行说明。

首先创建一个video.proto文件,内容如下:

syntax = "proto2";
package main;
​
message Video {
  required int64 id = 1; // 视频唯一表示
  required string author = 2; // 视频作者信息
  required string play_url = 3; // 视频播放地址
  required string cover_url = 4; // 视频封面地址
  required int64 favorite_count = 5; // 视频的点赞总数
  required int64 comment_count = 6; // 视频的评论总数
  required bool is_favorite = 7; // true-已点赞,false-未点赞
}
  • 第一行指定了proto版本,如果省略,编译器默认使用proto2语法,但为了显式声明避免一些错误,建议不要省略。
  • 第二行声明了包名,防止不同消息类型有命名冲突。
  • 消息类型使用message关键字定义,Video 是类型名,id、author、play_url等则是该消息的各个字段。
  • .proto文件可以添加注释,注释格式与C语言相同,单行注释使用//,多行注释使用/**/

注:具体的定义格式,可参考文末提供的学习资料,也可以查看官方文档,在此不进行详细说明。

4 编译.proto文件

如果正确完成了上述所有操作,那么只需要在文件目录下,执行如下命令即可:?

protoc --go_out=. video.proto
  • --go_out参数指明生成文件存放的路径,这里是使用.即当前路径下
  • video.proto即需要编译的文件

⚠️执行完命令,大概率你并不会得到生成的go文件,而是得到如下报错:

protoc-gen-go: unable to determine Go import path for "video.proto"
​
Please specify either:
        • a "go_package" option in the .proto source file, or
        • a "M" argument on the command line.
​
See https://developers.google.com/protocol-buffers/docs/reference/go-generated#package for more information.
​
--go_out: protoc-gen-go: Plugin failed with status code 1.

我们只需要在video.proto文件中加上:

option go_package=".";

整体文件如下:

syntax = "proto2";
package main;
​
option go_package=".";
​
message Video {
  required int64 id = 1; // 视频唯一表示
  required string author = 2; // 视频作者信息
  required string play_url = 3; // 视频播放地址
  required string cover_url = 4; // 视频封面地址
  required int64 favorite_count = 5; // 视频的点赞总数
  required int64 comment_count = 6; // 视频的评论总数
  required bool is_favorite = 7; // true-已点赞,false-未点赞
}

至此,再次执行编译命令,就可以获得生成的go文件:

image-20220512151829160.png

看到这里,恭喜你已经完成了使用protobuf的第一步!

参考及学习资料