У меня возникла проблема с управлением модулями Go и поколением протобуферов (с использованием 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
...
из-за другой версии сообщений несколько файлов протобуфера должны находиться в другом пространстве имен:
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)
Итак, в зависимости от параметра, используемого с компилятором протокола:
→ С --go_opt=paths=import
Дерево папок company.tld / proj / projpb создается protoc в корне проекта. Каждый объект находится в пакете с именем projpb или other, в подпакете other.
Сгенерированные объекты Proto, которые включают другие объекты пространства имен-d, имеют путь импорта import other "company.tld/proj/projpb/other"
(который задается параметром go_package
, но это неверно, потому что это не существующий модуль - go mod tidy / поставщик жалуется, что не может его найти).
Обычным файлам проекта необходим следующий путь импорта для доступа к объектам Generated Proto: import pb "company.tld/proj/subproj/company.tld/proj/projpb"
что кажется странным и неправильным.
→ С --go_opt=module=company.tld/proj
Папка projpb создается протоколом в корне проекта, и каждый сгенерированный .pb.go имеет пакет projpb или другой, в подпакете другой .
Сгенерированные объекты Proto, которые включают другие объекты пространства имен-d, по-прежнему имеют путь импорта import other "company.tld/proj/projpb/other"
(который по-прежнему задается параметром go_package
и все еще неверен, потому что это все еще несуществующий модуль - эти являются сгенерированными файлами ... зачем мне создавать модуль из них?).
Замечательно то, что с этим go_opt доступ к сгенерированным типам выглядит намного более нормальным с import pb "company.tld/proj/subproj/projpb"
.
Наконец я попробовал
- использование локального пути импорта в опции go_package в файлах .proto (это отклоняется во время сборки, потому что в сгенерированном объекте protobuffer будет
import other "./projpb/other"
) - использовать инструкцию replace в файле go.mod следующим образом:
replace (
company.tld/proj/projpb => ./projpb
company.tld/proj/projpb/other => ./projpb/other
)
(но go mod tidy / поставщик жалуется, что не может найти файл go.mod внутри сгенерированной папки ./projpb)
Кто-нибудь сталкивался с подобной проблемой? Или мне не хватает параметра команды, чтобы сообщить Go: «Я генерирую объекты протобуфера в пакете или пакет в пакете, и я просто хочу их использовать. Они не являются модулем, поэтому, пожалуйста, укажите правильные пути импорта к сгенерированному объекту и позвольте мне использовать их в моем коде ».
[Обновление 01]
Я попробовал go_opt=paths=source_relative
(вдохновленный этим билетом).
Я создал папку в Makefile, protoc генерирует файлы внутри.
Примечания:
- сгенерированные протоколы используют полный путь, указанный с параметром
go_package
, для связи друг с другом. - Пока для параметра
go_package
требуется полный путь, Go (go mod tidy / vendor) будет искать файл go.mod внутри созданной папки, содержащий сгенерированные протоколы.
Как правильно сообщить Go, что я не ищу модуль, но все же удовлетворяю ограничению полного пути параметра go_package в файле protobuffer?