Go使用protoc编译proto时paths=source_relative无法输出到指定pb目录
输出路径不符合预期是两处配置不匹配共同导致的:
.proto文件内go_package配置写法错误- 编译命令选用的路径模式参数和预期输出逻辑不匹配
paths=source_relative模式的输出规则为:最终生成路径 = --go_out指定的根路径 + 传入proto文件相对于命令执行位置的目录层级。当前执行命令时传入的proto路径为./proto/*.proto,protoc识别proto文件存放在proto子目录下,自然会在./pb下自动创建proto子目录存放生成文件,这就是./pb/proto目录出现的直接原因。
另外proto中写的option go_package="./grpc_tutorial/pb";属于无效配置:go_package字段必须填写生成代码对应的完整Go导入路径,不支持./开头的相对路径写法,该错误会导致后续其他服务引用pb包时出现导入路径异常。
1. 修正所有proto文件的go_package配置
将proto内的go_package替换为和项目模块匹配的正确值,对应go.mod定义的grpc_tutorial模块名、预期存放pb文件的./pb目录,示例配置如下:
syntax = "proto3"; // 格式:<模块名>/<pb目录相对项目根的路径>;<生成文件的Go包名> option go_package = "grpc_tutorial/pb;pb"; message Screen { string some_message = 1; string some_message_two = 2; bool some_bool = 3; }
分号后的pb为生成Go文件的package名,建议和存放目录名保持一致,降低后续导入的配置成本。
2. 执行匹配模块路径的编译命令
在项目根目录执行以下命令,即可将所有.pb.go文件直接输出到./pb目录:
protoc --go_out=. --go_opt=module=grpc_tutorial ./proto/*.proto
参数逻辑说明:
--go_out=.:指定代码输出根路径为当前项目根目录--go_opt=module=grpc_tutorial:开启模块路径匹配模式,生成文件时自动剔除go_package中与模块名grpc_tutorial匹配的前缀,剩余路径即为相对项目根的输出位置。由于go_package匹配后剩余路径为pb,生成文件会直接写入./pb目录,不会额外创建proto子目录。
如果偏好使用source_relative路径模式,也可以切换到proto目录下执行编译命令,同样能得到预期输出:
cd proto protoc --go_out=../pb/ --go_opt=paths=source_relative *.proto
该模式下protoc识别proto文件就在当前执行目录,无额外目录层级,会直接将生成文件写入上层的pb目录。注意该方式依然要求提前将go_package配置为正确的完整导入路径,禁止使用相对路径写法。
内容的提问来源于stack exchange,提问作者Jyhonn

