如何将protoc生成的gRPC服务端接口与客户端实现拆分到不同Go包
gRPC Go 生成代码拆分方案及最佳实践
标准最佳实践说明
你当前的拆分需求不符合gRPC Go官方的推荐实现,官方默认方案为:
将Protobuf消息模型、gRPC客户端存根、gRPC服务端抽象接口三类生成代码全部放在同一个公开包中(也就是你现在配置的
pkg/grpc目录)。
这么设计的核心理由是:
- 三类代码完全由同一份
.proto文件定义生成,属于强绑定关联的内容,同包存放可以天然保证版本一致性,避免客户端与服务端依赖的定义版本不匹配导致的调用异常 - 服务端侧只需将自己编写的业务实现逻辑放在
internal目录即可,生成的服务端抽象接口本身属于公开的API定义,不需要隐藏在internal中
如果你没有特殊的私有化需求,直接使用官方默认方案即可,不需要做额外的拆分改造。
自定义拆分实现步骤
如果你坚持要将服务端生成接口拆分到internal/pkg/grpc目录,可以按照如下步骤操作,你使用的工具版本完全支持以下配置:
1. 保留原有.proto配置
不需要修改option go_package的配置,保持原有内容即可:
syntax = "proto3"; option go_package = "github.com/<username>/<myservice>/pkg/grpc"; // 其余定义不变
2. 生成公共模型与客户端代码到pkg/grpc
运行以下命令,生成对外公开的消息模型和客户端存根:
# 生成.pb.go 消息模型文件 protoc --go_out=. --go_opt=paths=source_relative pkg/grpc/*.proto # 仅生成客户端gRPC代码到pkg/grpc protoc --go-grpc_out=. \ --go-grpc_opt=paths=source_relative \ --go-grpc_opt=client_only=true \ pkg/grpc/*.proto
3. 生成服务端接口到internal/pkg/grpc
运行以下命令生成仅服务端使用的接口代码,通过M参数配置导入映射,保证服务端代码可以正常引用pkg/grpc下的模型:
protoc --go-grpc_out=internal/pkg/grpc \ --go-grpc_opt=paths=source_relative \ --go-grpc_opt=server_only=true \ --go-grpc_opt=Mpkg/grpc/<替换为你的proto文件名>.proto=github.com/<username>/<myservice>/pkg/grpc \ pkg/grpc/*.proto
注意:如果有多个proto文件,需要为每个文件添加对应的
M参数配置。
后续维护注意
每次修改.proto文件后,需要同时执行上述两次生成命令,保证两端生成的代码版本完全一致。
内容的提问来源于stack exchange,提问作者Alexander
相关产品推荐
相关产品推荐

