带有 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.proto
和 grpc.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 文件(如果命名正确,会更安全一些)。
我正在尝试使用 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.proto
和 grpc.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 文件(如果命名正确,会更安全一些)。