Back to Go Zero

goctl rpc — RPC 代码生成

tools/goctl/rpc/README-cn.md

1.10.19.9 KB
Original Source

goctl rpc — RPC 代码生成

English | 中文

goctl rpc 是 goctl 脚手架下的 RPC 服务代码生成模块,基于 .proto 文件生成完整的 zRPC 服务代码。你只需编写 proto 定义和业务逻辑,其余代码均由工具自动生成。

特性

  • 贴近 protoc:与 protoc 完全兼容,透传所有 protoc 参数
  • 外部 Proto 导入:支持跨目录、跨包的 proto 导入,自动解析传递性依赖
  • 多服务模式:单个 proto 文件中定义多个 service,按服务名自动分组
  • 流式支持:支持服务端流、客户端流和双向流
  • Google 标准类型:自动识别 google.protobuf.* 类型并生成正确的 Go 导入
  • 客户端生成:自动生成封装好的 RPC 客户端代码

前置条件

bash
# 安装 protoc 插件
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

快速开始

方式一:一键创建服务

bash
goctl rpc new greeter

生成完整的项目结构:

greeter/
├── etc/
│   └── greeter.yaml
├── greeter/
│   ├── greeter.pb.go
│   └── greeter_grpc.pb.go
├── greeter.go
├── greeter.proto
├── greeterclient/
│   └── greeter.go
└── internal/
    ├── config/
    │   └── config.go
    ├── logic/
    │   └── pinglogic.go
    ├── server/
    │   └── greeterserver.go
    └── svc/
        └── servicecontext.go

方式二:基于 Proto 文件生成

  1. 生成 proto 模板:
bash
goctl rpc template -o=user.proto
  1. 初始化输出目录并生成服务代码:
bash
mkdir -p output && cd output && go mod init example.com/demo && cd ..
goctl rpc protoc user.proto \
  --go_out=output --go-grpc_out=output --zrpc_out=output \
  --go_opt=module=example.com/demo --go-grpc_opt=module=example.com/demo \
  --module=example.com/demo -I .

命令参考

goctl rpc protoc

.proto 文件生成 zRPC 服务代码。

bash
goctl rpc protoc <proto_file> [flags]

示例:

bash
# 基础用法
goctl rpc protoc user.proto \
  --go_out=output --go-grpc_out=output --zrpc_out=output \
  --go_opt=module=example.com/demo --go-grpc_opt=module=example.com/demo \
  --module=example.com/demo -I .

# 多服务模式
goctl rpc protoc multi.proto \
  --go_out=output --go-grpc_out=output --zrpc_out=output \
  --go_opt=module=example.com/demo --go-grpc_opt=module=example.com/demo \
  --module=example.com/demo -I . -m

# 导入外部 proto
goctl rpc protoc service.proto \
  --go_out=output --go-grpc_out=output --zrpc_out=output \
  --go_opt=module=example.com/demo --go-grpc_opt=module=example.com/demo \
  --module=example.com/demo -I . -I ./shared_protos

# 使用 Google 标准类型
goctl rpc protoc service.proto \
  --go_out=output --go-grpc_out=output --zrpc_out=output \
  --go_opt=module=example.com/demo --go-grpc_opt=module=example.com/demo \
  --module=example.com/demo -I .

参数说明:

参数缩写类型默认值说明
--zrpc_outstring必填zRPC 服务代码输出目录
--go_outstring必填protoc Go 代码输出目录
--go-grpc_outstring必填protoc gRPC 代码输出目录
--go_optstringprotoc-gen-go 选项(如 module=example.com/demo
--go-grpc_optstringprotoc-gen-go-grpc 选项(如 module=example.com/demo
--proto_path-Istring[]proto 导入搜索目录(可多次指定)
--multiple-mboolfalse多服务模式
--client-cbooltrue是否生成 RPC 客户端代码
--stylestringgozero文件命名风格
--modulestring自定义 Go module 名称
--name-from-filenameboolfalse使用文件名而非 package 名命名服务
--verbose-vboolfalse显示详细日志
--homestringgoctl 模板目录
--remotestring远程模板 Git 仓库地址
--branchstring远程模板分支

goctl rpc new

快速创建一个完整的 RPC 服务项目。

bash
goctl rpc new <service_name> [flags]

参数说明:

参数缩写类型默认值说明
--stylestringgozero文件命名风格
--client-cbooltrue是否生成 RPC 客户端代码
--modulestring自定义 Go module 名称
--verbose-vboolfalse显示详细日志
--ideaboolfalse生成 IDE 项目标记
--name-from-filenameboolfalse使用文件名而非 package 名命名服务
--homestringgoctl 模板目录
--remotestring远程模板 Git 仓库地址
--branchstring远程模板分支

goctl rpc template

生成 proto 文件模板。

bash
goctl rpc template -o=<output_file> [flags]

参数说明:

参数类型说明
-ostring输出文件路径(必填)
--homestringgoctl 模板目录
--remotestring远程模板 Git 仓库地址
--branchstring远程模板分支

功能详解

多服务模式(--multiple

当 proto 文件包含多个 service 定义时,必须使用 --multiple 标志。

protobuf
service SearchService {
  rpc Search(SearchReq) returns (SearchReply);
}

service NotifyService {
  rpc Notify(NotifyReq) returns (NotifyReply);
}

启用 --multiple 后的目录变化:

特性默认模式--multiple 模式
服务数量仅 1 个1 个或多个
客户端目录以服务名命名固定为 client/
代码组织扁平结构按服务名分组

--multiple=false(默认)的目录结构:

output/
├── greeterclient/
│   └── greeter.go
├── internal/
│   ├── logic/
│   │   └── sayhellologic.go
│   └── server/
│       └── greeterserver.go
└── ...

--multiple=true 的目录结构:

output/
├── client/
│   ├── searchservice/
│   │   └── searchservice.go
│   └── notifyservice/
│       └── notifyservice.go
├── internal/
│   ├── logic/
│   │   ├── searchservice/
│   │   │   └── searchlogic.go
│   │   └── notifyservice/
│   │       └── notifylogic.go
│   └── server/
│       ├── searchservice/
│       │   └── searchserviceserver.go
│       └── notifyservice/
│           └── notifyserviceserver.go
└── ...

外部 Proto 导入(--proto_path

通过 -I / --proto_path 指定额外的 proto 搜索目录,支持以下场景:

  • 同目录导入import "types.proto";
  • 子目录导入import "common/types.proto";
  • 外部目录导入:proto 文件位于项目外部
  • 传递性导入:A 导入 B,B 导入 C,goctl 自动递归解析
  • 跨包导入:不同 go_package 的 proto 文件,自动生成正确的 Go 导入
bash
# 从多个目录搜索 proto 文件
goctl rpc protoc service.proto \
  --go_out=output --go-grpc_out=output --zrpc_out=output \
  --go_opt=module=example.com/demo --go-grpc_opt=module=example.com/demo \
  --module=example.com/demo \
  -I . -I ./shared_protos -I /path/to/external_protos

服务命名

默认情况下,服务名称来自 proto 的 package 名称(例如 package user; → 服务名 user)。这使得多个 proto 文件可以共享同一个 package:

protos/
├── user_base.proto      # package user;
├── user_auth.proto      # package user;
└── user_profile.proto   # package user;

三个文件会生成到同一个 user 服务中。

如需使用 proto 文件名命名(旧版行为),请添加 --name-from-filename 标志。

流式 RPC

支持 gRPC 的三种流式模式:

protobuf
service StreamService {
  rpc ServerStream(Req) returns (stream Reply);       // 服务端流
  rpc ClientStream(stream Req) returns (Reply);       // 客户端流
  rpc BidiStream(stream Req) returns (stream Reply);  // 双向流
}

Google 标准类型

goctl 自动识别并正确处理 Google protobuf 标准类型:

Proto 类型Go 类型
google.protobuf.Emptyemptypb.Empty
google.protobuf.Timestamptimestamppb.Timestamp
google.protobuf.Durationdurationpb.Duration
google.protobuf.Anyanypb.Any
google.protobuf.Structstructpb.Struct
google.protobuf.FieldMaskfieldmaskpb.FieldMask
google.protobuf.*Valuewrapperspb.*Value

这些类型可直接用作 RPC 参数类型,goctl 会自动生成正确的导入。


完整示例

详见 example/ 目录,包含 10 个完整示例,覆盖所有生成场景。

#示例场景
01基础服务单服务,无导入
02同级导入导入同目录 proto
03子目录导入导入子目录 proto
04传递性导入A → B → C 依赖链
05多服务--multiple 模式
06标准类型消息中使用 Timestamp 等
07外部 Proto(同包)外部 proto,相同 go_package
08外部 Proto(跨包)外部 proto,不同 go_package
09标准类型作参数Empty/Timestamp 作为 RPC 参数
10流式通信服务端/客户端/双向流