带有 grpc 的 protobuf for Go 在拆分包中

protobuf with grpc for Go in split packages

我正在尝试使用 here 所述的六边形架构来制作我的 Go 项目。 在我的项目中,我正在使用 .proto 文件中的 protoc 生成的 gRPC 通信。

目录结构:

|- grpc.proto
|-internal
  |-core
    |-domain
  |-services
    |- grpcprotocol

我的 grpc.proto 文件有 go_package 选项指向我的 Go 项目中的特定目录

syntax = "proto3";
option go_package = "github.com/myuser/myrepo/internal/core/services/grpcprotocol";
...

使用 protoc --go_out=internal/core/domain --go_opt=paths=source_relative --go-grpc_out=internal/core/services/grpcprotocol --go-grpc_opt=paths=source_relative ports.proto 我能够在 internal/core/domain 中生成两个 grpc.pb.go 文件目录和 grpc_grpc.pb.go 文件在 internal/core/services/grpcprotocol 目录中。

然而,grpc.pb.go 有一个名为 grpcprotocol 的包,而它应该有一个名为 domain 的包(我也使用其他类型在单独的 Go 文件中定义)。 grpc_grpc.pb.go 文件中的代码使用了 grpc.pb.go 中定义的类型,但没有导入(它把它当作在同一个包中定义。

是否可以将这两个文件拆分成单独的 Go 包并强制执行 grpc_grpc.pb.go 中的代码从域目录导入类型而不是按定义处理它们在同一个包裹里?

最好的解决方案是将 grpcprotocol 中所需的代码与 domain 中所需的代码分离到单独的文件中。如:

domain.proto

syntax = "proto3";
package domain;
option go_package = "github.com/myuser/myrepo/internal/core/domain";

//...

grpc.proto

syntax = "proto3";
package grpcprotocol;
option go_package = "github.com/myuser/myrepo/internal/core/services/grpcprotocol";

//...

然后你可以在你的 grpc.proto 中导入你的 domain.proto,只需写 import "domain.proto";,提供 --proto_path 如果 domain.protogrpc.proto 不在同一个目录中。最后,要在 grpc.proto 中引用来自 domain.proto 的对象,您可以这样写:

domain.AnObject

之后你可以利用--go_opt=module--go-grpc_opt=module,去掉go_package中的模块名,在正确的地方生成代码。喜欢:

protoc --go_out=. --go_opt=module=github.com/myuser/myrepo --go-grpc_out=. --go-grpc_opt=module=github.com/myuser/myrepo *.proto

这将做的是,它将从每个 go_package 中删除 github.com/myuser/myrepo 并且基本上从模块的根开始。这就是为什么你可以做 --go_out=.--go-grpc_out=..

希望对您有所帮助,让我知道如何进一步改进我的答案。

备注

  • Protobuf 包和go_package 不一样。前者仅用于 protobuf 以提供上下文,它扩展了限定名称。 go_package 在 go 代码生成过程中使用。
  • proto 文件中的 package 是可选的,它使事情更清楚,没有人可以在不指定完全限定名称的情况下滥用您的 proto 文件(如果命名正确,会更安全一些)。