2023-03-29
protobuf go
protoc 编译 proto文件生成go的一些说明和实验:
protoc 生成 go 的语法:
protoc -I=$BASE_SRC_DIR --go_out=$DST_DIR --go_opt=${options} $SUB_SRC_DIR/addressbook.proto
我们有如下的项目,目录结构 和 bar.proto 文件,下文所涉及的生成测试都基于这个目录结构和文件:
- 目录结构
.
├── build.sh
├── out
├── protos
│ └── bar.proto
└── readme.md
- bar.proto
syntax="proto3";
option go_package="example.com/project/foo";
message test {
string id =1;
}
一、-I 参数
指定定义文件proto的路径。通俗来讲就是告诉protoc从哪些文件夹下,寻找proto文件,默认从当前文件夹下找。
实验
# case1. BASE_SRC_DIR=./
protoc -I=./ --go_out=out --go_opt=paths=import bar.proto
# Could not make proto path relative: bar.proto: No such file or directory
# case2. BASE_SRC_DIR=./
protoc -I=./ --go_out=out --go_opt=paths=import protos/bar.proto
# case3. BASE_SRC_DIR=protos
protoc -I=./protos --go_out=out --go_opt=paths=import bar.proto
# case4. BASE_SRC_DIR=protos
protoc -I=./protos --go_out=out --go_opt=paths=import protos/bar.proto
其中,case1 返回找不到bar.proto 文件,case2、case3和case4 皆顺利生成。
case2,case3能执行成功是,在protoc的执行路径下,存在文件 SUB_SRC_DIR + BASE_SRC_DIR + {filename}.proto` 是存在的。
case4 中: protos/protos/bar.proto (SUB_SRC_DIR + SUB_SRC_DIR + ${filename}.proto 的值)
注意:case4 和 case3,及case2的结果相同,但过程是不同的。
二、 --go_out
go_out 的参数是个文件路径,指定生成文件的输出目录,此目录需事先存在。
go_opt 和 go import 决定的路径,在此跟路径之下。
三、 --go_opt 选项参数
还是以上面的文件为例: protos/bar.proto 文件,根据编译中 --go_opt的不同,生成文件的位置也不同
- paths=import
默认参数:指定生成文件输出路径。 默认行为是指定生成文[.pb.go]件位于 proto 定义的导出路径的后面;
protoc -I=./ --go_out=out --go_opt=paths=import protos/bar.proto
.
├── art.md
├── build.sh
├── out
│ └── example.com
│ └── project
│ └── foo
│ └── bar.pb.go
├── protos
│ └── bar.proto
└── readme.md
- module=$PREFIX
文件位置位于 导入路径
减去$PREFIX
的部分
protoc -I=./ --go_out=out --go_opt=module=example.com/project protos/bar.proto
.
├── art.md
├── build.sh
├── out
│ └── foo
│ └── bar.pb.go
├── protos
│ └── bar.proto
└── readme.md
- paths=source_relative
该方式可生成和定义文件一致的目录
protoc -I=./ --go_out=out --go_opt=paths=source_relative protos/bar.proto
.
├── art.md
├── build.sh
├── out
│ └── protos
│ └── bar.pb.go
├── protos
│ └── bar.proto
└── readme.md
四、. package 指定方式
为了生成 Go 代码,必须为每个 .proto 文件提供 Go 包的导入路径(包括那些被生成的 .proto 文件传递依赖的文件)。
指定 Go 导入路径的方式有两种:
-
定义在 proto 文件中
在定义proto文件时,指定go_package选项, 该选项定义包的导入路径,Go包名将是导入路径的最后一个字段,通常不建议添加。
例如,
syntax="proto3";
option go_package="example.com/project/foo;package_name";
.
├── art.md
├── build.sh
├── out
│ └── example.com
│ └── project
│ └── foo
│ └── bar.pb.go
├── protos
│ └── bar.proto
└── readme.md
- M flag
在 protoc 调用生成的时候,使用 M${PROTO_FILE}=${GO_IMPORT_PATH}
方式,更改指定包导入路径
仍然使用上面的文件为例:
protoc --proto_path=src \
--go_opt=Mprotos/buzz.proto=example.com/project/protos/fizz \
--go_opt=Mprotos/bar.proto=example.com/project/protos/foo \
protos/buzz.proto protos/bar.proto
如果两种同时指定,命令行中指定的优先级别高。