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?
CodePudding user response:
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. Thego_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).