【发布时间】:2021-09-08 03:26:13
【问题描述】:
我遇到了 Go 模块管理和生成 protobuffers 的问题(使用 go1.16,protoc-gen-go@latest)。
我有这个项目结构:
subproj
├── go.mod (module company.tld/proj/subproj)
├── subproj.go (entry point : package main)
├── proto (folder containing .proto files)
├── packageFolder
| └── file1.go (package packageFolder)
└── Makefile (used to generate *.pb.go and build subproj binary)
proto 文件夹被其他项目使用(显然...)(通过 git 子模块)。
原型如下:
syntax = "proto3"
option csharp_namespace = "Proj.Proto";
option go_package = "company.tld/proj/projpb";
package entity.proj
...
由于消息版本不同,很少有 protobuffer 文件需要在另一个“命名空间”中:
option go_package = "company.tld/proj/projpb/other";
package entity.proj.other
在我的 Makefile 中,我尝试在正确的位置生成正确的 *.pb.go:
# Proto sources
PROTO= $(wildcard ${PROTODIR}/*.proto)
PBGO= $(PROTO:.proto=.pb.go)
MODULE_NAME=company.tld/proj
GO_OPT_FLAG= --go_opt=module=${MODULE_NAME}
GRPC_OPT_FLAG= --go-grpc_opt=module=${MODULE_NAME}
#GO_OPT_FLAG= --go_opt=paths=import
#GRPC_OPT_FLAG= --go-grpc_opt=paths=import
.PHONY: clean install proto
## Builds the project
build: proto
go build ${LDFLAGS} -o ${BINARY}
$(PROTOBUF_GO_PLUGIN):
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
$(GRPC_GO_PLUGIN):
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
%.pb.go: %.proto | $(PROTOBUF_GO_PLUGIN) $(GRPC_GO_PLUGIN)
protoc --proto_path=${PROTODIR} --go_out=. ${GO_OPT_FLAG} --go-grpc_out=. ${GRPC_OPT_FLAG} $<
proto: $(PBGO)
因此,取决于 protoc 编译器使用的选项:
→ 与--go_opt=paths=import
文件夹树company.tld/proj/projpb由项目根目录的protoc创建。每个对象都在一个名为 projpb 或 other 的包中,在子包 other 中。
生成的 Proto 对象,包括 other 命名空间-d 对象,具有导入路径 import other "company.tld/proj/projpb/other"(由 go_package 选项带来,但这是错误的,因为它不是现有模块 - go mod tidy/vendor 抱怨找不到它)。
普通项目文件需要以下导入路径才能到达生成的 Proto 对象:import pb "company.tld/proj/subproj/company.tld/proj/projpb"
这看起来很奇怪,而且不是正确的做法。
→ 与--go_opt=module=company.tld/proj
一个文件夹projpb由protoc在项目的根目录下创建,每个生成的.pb.go都有包projpb或other,在其他的子包。
生成的 Proto 对象,包括 other 命名空间-d 对象,仍然具有导入路径 import other "company.tld/proj/projpb/other"(仍然由 go_package 选项带来并且仍然是错误的,因为这仍然是一个不存在的模块 - 这些是生成的文件......我为什么要创建这些模块?)。
很酷的是,有了这个 go_opt,使用import pb "company.tld/proj/subproj/projpb" 访问生成的类型看起来更加正常。
最后,我尝试了
- 在 .proto 文件中的 go_package 选项上使用本地导入路径(在构建时被拒绝,因为在生成的 protobuffer 对象中会有一个
import other "./projpb/other") - 在 go.mod 文件中使用 replace 指令,如下所示:
replace (
company.tld/proj/projpb => ./projpb
company.tld/proj/projpb/other => ./projpb/other
)
(但是 go mod tidy/vendor 抱怨在生成的文件夹 ./projpb 中找不到 go.mod 文件)
有人遇到过类似的问题吗?或者我是否缺少一个命令选项来告诉 Go,«我在一个包中生成 protobuffer 对象,或者在一个包中生成包,我只是想使用它们。它们不是模块,所以请提供生成对象的正确导入路径,并让我在代码中使用它们»。
[更新 01]
我尝试了go_opt=paths=source_relative(灵感来自ticket)。
我在Makefile中创建了文件夹,protoc在里面生成文件。
备注:
- 生成的 protos 使用通过
go_package选项指定的完整路径来相互关联。 - 只要
go_package选项需要完整路径,Go (go mod tidy/vendor) 就会在创建的文件夹中搜索 go.mod 文件,其中包含生成的原型。
告诉 Go 我不是在寻找模块,但仍然满足 go_package 选项在 protobuffer 文件中的完整路径约束的正确方法是什么?
【问题讨论】:
标签: go protocol-buffers go-modules protoc