protoc生成Go/gRPC代码路径配置及导入问题求助
想让protoc把生成的文件输出到所有.proto所在文件夹内的子目录里,但protoc的命令实在晦涩,查了文档看似全覆盖,实际操作就是跑不通。
我的protobuf文件都存在proto文件夹里,部分文件需要导入其他.proto,初始写法如下:
package proto; option go_package = "github.com/me/golang-grpc-server/proto"; import "proto/another_proto.proto"; message Proto1 { ... ... repeated proto.AnotherProto another_proto = 6; }
按道理这应该能正常运行,但protoc直接报错。执行以下命令:
protoc --proto_path=proto --go_out=out --go_opt=paths=source_relative --go-grpc_out=out --go-grpc_opt=paths=source_relative proto1.proto another_proto.proto
抛出错误:
proto/another_proto.proto: File not found. proto1.proto:7:1: Import "proto/another_proto.proto" was not found or had errors. proto1.proto:16:14: "proto.AnotherProto" is not defined. proto1.proto:40:14: "AnotherProto" is not defined.
如果把another_proto.proto放在命令里的proto1.proto前面,错误变成:
proto/another_proto.proto: File not found. proto1.proto:7:1: Import "proto/another_proto.proto" was not found or had errors. proto1.proto:16:14: "proto.AnotherProto" seems to be defined in "another_proto.proto", which is not imported by "proto1.proto". To use it here, please add the necessary import. proto1.proto:40:14: "proto.AnotherProto" seems to be defined in "another_proto.proto", which is not imported by "proto1.proto". To use it here, please add the necessary import.
移除--proto_path参数后的尝试
后来移除了--proto_path=proto参数,给每个protobuf文件名加上proto\前缀,这次终于没再报之前的错误,但生成的文件都跑到out\proto目录下了——这和预期不符,因为按照文档说明,--go_opt=paths=source_relative应该让输出文件和输入文件在相同的相对目录下:
If the paths=source_relative flag is specified, the output file is
placed in the same relative directory as the input file. For example,
an input file protos/buzz.proto results in an output file at
protos/buzz.pb.go.
试了用--go_out=proto/out,结果生成的文件又跑到proto/out/proto里了。估计是因为文件名前的proto/前缀导致的,只能暂时先用out/proto这个路径。
按建议调整包结构后的问题
不确定是不是理解对了@Daz的建议,按自己的想法做了调整:
修改了Proto1的内容:
package src; option go_package = "github.com/me/golang-grpc-server/proto/src"; import "src/another_proto.proto"; message Proto1 { ... ... repeated src.AnotherProto another_proto = 6; }
把所有protobuf文件移到proto下的src子文件夹,同时修改了每个文件的go_package(末尾加/src)和导入语句适配这个结构。然后把protoc命令改成:
protoc --proto_path=proto/src --go_out=./out --go_opt=paths=source_relative --go-grpc_out=./out --go-grpc_opt=paths=source_relative proto/src/*.proto
用*.proto确实方便,但调整后还是不行。问题从protobuf文件本身就开始了:如果用"src/another_proto.proto"作为导入路径,代码检查工具提示“路径未找到或存在错误”;换成"proto/src/another_proto.proto"的话,代码检查的错误消失了,但执行protoc命令又会抛出之前的“未找到...”错误。
最终调整后的状态
这情况真的闹心,怀疑是protoc-go的bug或者功能缺失。为了让生成的存根文件路径更合理,我修改了--proto_path参数的层级,每次加一个文件夹,就得同步改protobuf文件的go_package和导入语句,不然就会报“未找到protobuf文件”的错误。现在我的protobuf文件内容是这样的:
package src; option go_package = "github.com/me/golang-grpc-server/proto/src"; import "another_proto.proto"; message Proto1 { ... ... repeated AnotherProto another_proto = 6; }
写法倒是简洁了,但代码检查工具不认可。估计就像@Daz说的,protobuf并没有真正用Go的包系统,导致代码检查工具识别不了导入语句。现在项目能构建,但有两个文件会显示错误。当前用的命令会把存根文件放到和proto文件夹同级的out目录里:
protoc --proto_path=proto/src --go_out=out --go_opt=paths=source_relative --go-grpc_out=out --go-grpc_opt=paths=source_relative proto/src/*.proto
内容的提问来源于stack exchange,提问作者rminaj

