Protobuf用法

proto文件学习

Posted by 果果 on September 21, 2022

一 protobuf介绍

Protobuf 全称 Protocol Buffer,是 Google 公司于2008年开源的一种语言无关、平台无关、可扩展的用于序列化结构化数据——类似于XML,但比XML更小、更快、更简单,它可用于(数据)通信协议、数据存储等。你只需要定义一次你想要的数据结构,然后你就可以使用特殊生成的源代码来轻松地从各种数据流和各种语言中写入和读取你的结构化数据。目前 Protobuf 被广泛用作微服务中的通信协议。

二 安装 protobuf

go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest //生成grpc代码

三 生成go代码

在调用protoc时,通过传递 go_opt 标志来提供特定于 protocol-gen-go 的标志位参数。可以传递多个go_opt标志位参数。例如,当执行下面的命令时

protoc --proto_path=src \
	   --go_out=out \
 	   --go_opt=paths=source_relative \
	   foo.proto bar/baz.proto

## 输出文件的名称是通过将.proto 扩展名替换为.pb.go 而创建的。

编译器将从 src 目录中读取输入文件 foo.proto 和 bar/baz.proto,并将输出文件 foo.pb.go 和 bar/baz.pb.go 写入 out 目录。如果需要,编译器会自动创建嵌套的输出子目录,但不会创建输出目录本身。

参数说明

  • paths=import:输出文件放在以 Go 包的导入路径命名的目录中。例如,protos/buzz.proto文件中带有example.com/project/protos/fizz的导入路径,则输出的生成文件会保存在example.com/project/protos/fizz/buzz.pb.go。如果未指定路径标志,这就是默认输出模式。
  • module=$PREFIX:输出文件放在以 Go 包的导入路径命名的目录中,但是从输出文件名中删除了指定的目录前缀。例如,输入文件 pros/buzz.proto,其导入路径为 example.com/project/protos/fizz 并指定example.com/project为module前缀,结果会产生一个名为 pros/fizz/buzz.pb.go 的输出文件。在module路径之外生成任何 Go 包都会导致错误。此模式对于将生成的文件直接输出到 Go 模块非常有用。
  • paths=source_relative:输出文件与输入文件放在相同的相对目录中。例如,一个protos/buzz.proto输入文件会产生一个位于protos/buzz.pb.go的输出文件

package

为了生成 Go 代码,必须为每个 .proto 文件(包括那些被生成的 .proto 文件传递依赖的文件)提供 Go 包的导入路径。有两种方法可以指定 Go 导入路径:

  • 通过在 .proto 文件中声明它,或者
  • 通过在调用 protoc 时在命令行上声明它。

我们建议在 .proto 文件中声明它,以便 .proto 文件的 Go 包可以与 .proto 文件本身集中标识,并简化调用 protoc 时传递的标志集。

option go_package = "example.com/project/protos/fizz";

四 Go使用protoc示例

// proto/book/book.proto

syntax = "proto3";

package book;

// 声明生成Go代码的导入路径(import path)
option go_package = "github.com/Q1mi/demo/proto/book";

message price {
    int64 marketPrice = 1;
    int64 salePrice = 2;
}

项目当前的目录结构如下:

demo
└── proto
    └── book
        └── price.proto

生成代码 假设我们想把最终生成的Go代码还保存在proto文件夹中,那么就可以执行下面的命令。

protoc \
--proto_path=proto \
--go_out=proto \
--go_opt=paths=source_relative \
book/price.proto

其中:

  • –proto_path=proto 表示从proto目录下读取proto文件。
  • –go_out=proto 表示生成的Go代码保存的路径。
  • –go_opt=paths=source_relative 表示输出文件与输入文件放在相同的相对目录中。
  • account/account.proto 表示在proto目录下的account/account.proto文件。

执行上述命令将会在proto目录下生成account/account.pb.go文件。

demo
└── proto
    └── book
        ├── price.pb.go
        └── price.proto

此处命令可以简写为:

protoc \
--go_out=. \
--go_opt=paths=source_relative \
proto/book/price.proto

如果想要将生成的Go代码保存在其他文件夹中(例如pb文件夹)

protoc \
--proto_path=proto \
--go_out=pb \
--go_opt=paths=source_relative \
book/price.proto

执行上面的命令便会在demo/pb文件夹下生成Go代码。

demo
├── pb
   └── book
       └── price.pb.go
└── proto
    └── book
        ├── price.pb.go
        └── price.proto