Go中使用分割包的protobuf和grpc

huangapple go评论86阅读模式
英文:

protobuf with grpc for Go in split packages

问题

我正在尝试使用六边形架构来构建我的Go项目,就像这里所描述的那样。
在我的项目中,我使用protoc.proto文件生成了一个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文件,并在internal/core/services/grpcprotocol目录中生成grpc_grpc.pb.go文件。

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

是否可能将这两个文件拆分为单独的Go包,并强制grpc_grpc.pb.go中的代码导入来自domain目录的类型,而不是将其视为在同一个包中定义的类型?

英文:

I'm trying to make my Go project using hexagonal architecture as described here.
In my project I'm using a gRPC communication generated with protoc from .proto file.

The directories structure:

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

And my grpc.proto file has go_package option that points to a specific directory in my Go project

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

Using 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 I'm able to generate both grpc.pb.go file in internal/core/domain directory and grpc_grpc.pb.go file inside internal/core/services/grpcprotocol directory.

However, grpc.pb.go has a go package named grpcprotocol while it should have a package named domain (I also use other types defined there in separate Go files).
Also grpc_grpc.pb.go file has code that uses types defined in grpc.pb.go without imports (it treats it as if it was defined in the same package).

Is it possible to split those two files into separate Go packages and enforce code that's in grpc_grpc.pb.go to import types from domain directory instead of treating them as defined in the same package?

答案1

得分: 3

你在这里的最佳解决方案是将你想要的代码分别放在grpcprotocoldomain中,放在不同的文件中。例如:

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";,如果domain.protogrpc.proto不在同一个目录下,可以提供一个--proto_path。最后,在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文件(如果命名正确,会更安全)。
英文:

Your best solution here is too separate the code that you want in grpcprotocol and the one you want into domain, into separate files. Such as:

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";

//...

Then you could import your domain.proto in your grpc.proto, by simply writing import "domain.proto";, provide a --proto_path if domain.proto and grpc.proto are not in the same directory. And finally to reference an object from domain.proto in grpc.proto you can write:

domain.AnObject

After that you can take advantage of the --go_opt=module and --go-grpc_opt=module, to strip the module name in go_package and generate the code at the right place. Like:

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

What this will do is that, it will remove github.com/myuser/myrepo from each go_package and basically start from the root of your module. That's why you can do a --go_out=. and --go-grpc_out=..

Hope that helps, let me know how I can further improve my answer.

Notes

  • Protobuf package and go_package are not the same. The former is only used for protobuf in order to give context and it extends the qualified name. The go_package is used during go code generation.
  • The package in the proto file is optional, it makes things more clear and nobody can misuse you proto file without specifying the fully qualified name (little bit safer, if named properly).

huangapple
  • 本文由 发表于 2022年4月21日 02:13:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/71944360.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定