mirror of
https://github.com/zeromicro/go-zero.git
synced 2026-05-10 16:30:01 +08:00
feat(goctl/rpc): support external proto imports with cross-package ty… (#5472)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
100
tools/goctl/rpc/example/01-basic/README-cn.md
Normal file
100
tools/goctl/rpc/example/01-basic/README-cn.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# 示例 01:基础 RPC 服务
|
||||
|
||||
这是使用 goctl 生成 RPC 服务的最简单示例。
|
||||
|
||||
## Proto 定义
|
||||
|
||||
一个 `greeter.proto` 文件,包含一个服务和一个 RPC 方法,无外部导入。
|
||||
|
||||
`go_package` 使用完整的模块路径:
|
||||
|
||||
```protobuf
|
||||
option go_package = "example.com/demo/greeter";
|
||||
```
|
||||
|
||||
## 生成命令
|
||||
|
||||
### 方式一:使用 `goctl rpc new` 快速创建
|
||||
|
||||
```bash
|
||||
# 一条命令创建完整的 RPC 项目
|
||||
goctl rpc new greeter
|
||||
```
|
||||
|
||||
该命令会同时生成 proto 文件和服务代码:
|
||||
|
||||
```
|
||||
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 文件生成
|
||||
|
||||
首先,在输出目录中初始化 `go.mod`:
|
||||
|
||||
```bash
|
||||
mkdir -p output && cd output && go mod init example.com/demo && cd ..
|
||||
```
|
||||
|
||||
然后生成代码:
|
||||
|
||||
```bash
|
||||
goctl rpc protoc greeter.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 .
|
||||
```
|
||||
|
||||
生成的目录结构:
|
||||
|
||||
```
|
||||
output/
|
||||
├── etc
|
||||
│ └── greeter.yaml
|
||||
├── go.mod
|
||||
├── greeter
|
||||
│ ├── greeter.pb.go
|
||||
│ └── greeter_grpc.pb.go
|
||||
├── greeter.go
|
||||
├── greeterclient
|
||||
│ └── greeter.go
|
||||
└── internal
|
||||
├── config
|
||||
│ └── config.go
|
||||
├── logic
|
||||
│ └── sayhellologic.go
|
||||
├── server
|
||||
│ └── greeterserver.go
|
||||
└── svc
|
||||
└── servicecontext.go
|
||||
```
|
||||
|
||||
## 要点说明
|
||||
|
||||
- 这是最简单的场景:一个 proto 文件、一个服务、一个 RPC 方法。
|
||||
- `go_package` 使用完整的模块路径(`example.com/demo/greeter`),而非相对路径。
|
||||
- `--module` 告诉 goctl Go 模块名;`--go_opt=module=...` 和 `--go-grpc_opt=module=...` 告诉 protoc 从输出路径中去除模块前缀。
|
||||
- `--zrpc_out` 指定 goctl 生成的服务代码输出目录。
|
||||
- `--go_out` 和 `--go-grpc_out` 指定 protoc 生成代码的输出目录。
|
||||
- 编辑逻辑文件(`internal/logic/sayhellologic.go`)来实现业务逻辑。
|
||||
100
tools/goctl/rpc/example/01-basic/README.md
Normal file
100
tools/goctl/rpc/example/01-basic/README.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# Example 01: Basic RPC Service
|
||||
|
||||
This is the simplest example of generating an RPC service with goctl.
|
||||
|
||||
## Proto Definition
|
||||
|
||||
A single `greeter.proto` file with one service and one RPC method, no external imports.
|
||||
|
||||
The `go_package` uses a full module path:
|
||||
|
||||
```protobuf
|
||||
option go_package = "example.com/demo/greeter";
|
||||
```
|
||||
|
||||
## Generation Commands
|
||||
|
||||
### Method 1: Quick Start with `goctl rpc new`
|
||||
|
||||
```bash
|
||||
# Create a complete RPC project with one command
|
||||
goctl rpc new greeter
|
||||
```
|
||||
|
||||
This generates the proto file and service code together:
|
||||
|
||||
```
|
||||
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
|
||||
```
|
||||
|
||||
### Method 2: Generate from an Existing Proto
|
||||
|
||||
First, initialize the output directory with a `go.mod`:
|
||||
|
||||
```bash
|
||||
mkdir -p output && cd output && go mod init example.com/demo && cd ..
|
||||
```
|
||||
|
||||
Then generate the code:
|
||||
|
||||
```bash
|
||||
goctl rpc protoc greeter.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 .
|
||||
```
|
||||
|
||||
Generated directory structure:
|
||||
|
||||
```
|
||||
output/
|
||||
├── etc
|
||||
│ └── greeter.yaml
|
||||
├── go.mod
|
||||
├── greeter
|
||||
│ ├── greeter.pb.go
|
||||
│ └── greeter_grpc.pb.go
|
||||
├── greeter.go
|
||||
├── greeterclient
|
||||
│ └── greeter.go
|
||||
└── internal
|
||||
├── config
|
||||
│ └── config.go
|
||||
├── logic
|
||||
│ └── sayhellologic.go
|
||||
├── server
|
||||
│ └── greeterserver.go
|
||||
└── svc
|
||||
└── servicecontext.go
|
||||
```
|
||||
|
||||
## Key Points
|
||||
|
||||
- This is the simplest scenario: one proto file, one service, one RPC method.
|
||||
- The `go_package` uses a full module path (`example.com/demo/greeter`), not a relative path.
|
||||
- The `--module` flag tells goctl the Go module name; `--go_opt=module=...` and `--go-grpc_opt=module=...` tell protoc to strip the module prefix from output paths.
|
||||
- The `--zrpc_out` flag specifies where the goctl-generated service code goes.
|
||||
- The `--go_out` and `--go-grpc_out` flags specify where protoc-generated code goes.
|
||||
- Edit the logic file (`internal/logic/sayhellologic.go`) to implement your business logic.
|
||||
17
tools/goctl/rpc/example/01-basic/greeter.proto
Normal file
17
tools/goctl/rpc/example/01-basic/greeter.proto
Normal file
@@ -0,0 +1,17 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package greeter;
|
||||
|
||||
option go_package = "example.com/demo/greeter";
|
||||
|
||||
message HelloReq {
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
message HelloReply {
|
||||
string message = 1;
|
||||
}
|
||||
|
||||
service Greeter {
|
||||
rpc SayHello(HelloReq) returns (HelloReply);
|
||||
}
|
||||
77
tools/goctl/rpc/example/02-import-sibling/README-cn.md
Normal file
77
tools/goctl/rpc/example/02-import-sibling/README-cn.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# 示例 02:导入同级 Proto 文件
|
||||
|
||||
本示例演示如何导入同一目录下的 proto 文件。
|
||||
|
||||
## Proto 定义
|
||||
|
||||
同一目录下的两个 proto 文件共享相同的 `go_package`:
|
||||
|
||||
- `types.proto` — 定义共享消息类型(`User`)。
|
||||
- `user.proto` — 定义 RPC 服务,导入 `types.proto`。
|
||||
|
||||
两个文件使用相同的 `go_package`,采用完整模块路径:
|
||||
|
||||
```protobuf
|
||||
option go_package = "example.com/demo/pb";
|
||||
```
|
||||
|
||||
`user.proto` 通过以下方式导入 `types.proto`:
|
||||
|
||||
```protobuf
|
||||
import "types.proto";
|
||||
```
|
||||
|
||||
## 生成命令
|
||||
|
||||
首先,在输出目录中初始化 `go.mod`:
|
||||
|
||||
```bash
|
||||
mkdir -p output && cd output && go mod init example.com/demo && cd ..
|
||||
```
|
||||
|
||||
然后生成代码:
|
||||
|
||||
```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 .
|
||||
```
|
||||
|
||||
生成的目录结构:
|
||||
|
||||
```
|
||||
output/
|
||||
├── etc
|
||||
│ └── usersvc.yaml
|
||||
├── go.mod
|
||||
├── internal
|
||||
│ ├── config
|
||||
│ │ └── config.go
|
||||
│ ├── logic
|
||||
│ │ ├── createuserlogic.go
|
||||
│ │ └── getuserlogic.go
|
||||
│ ├── server
|
||||
│ │ └── userserviceserver.go
|
||||
│ └── svc
|
||||
│ └── servicecontext.go
|
||||
├── pb
|
||||
│ ├── types.pb.go
|
||||
│ ├── user.pb.go
|
||||
│ └── user_grpc.pb.go
|
||||
├── userservice
|
||||
│ └── userservice.go
|
||||
└── usersvc.go
|
||||
```
|
||||
|
||||
## 要点说明
|
||||
|
||||
- 两个 proto 文件(`user.proto` 和 `types.proto`)共享相同的 `go_package = "example.com/demo/pb"`,编译到同一个 Go 包中。
|
||||
- `user.proto` 通过 `import "types.proto"` 导入 `types.proto`。
|
||||
- 多个 proto 文件共享相同的 `go_package` 时,它们会编译到同一个 Go 包中。
|
||||
- 只需将包含 `service` 定义的 proto 文件传递给 `goctl rpc protoc`。
|
||||
- 导入的 proto 文件会被 protoc 自动编译,并由 goctl 自动解析。
|
||||
77
tools/goctl/rpc/example/02-import-sibling/README.md
Normal file
77
tools/goctl/rpc/example/02-import-sibling/README.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# Example 02: Importing a Sibling Proto File
|
||||
|
||||
This example demonstrates importing a proto file from the same directory.
|
||||
|
||||
## Proto Definition
|
||||
|
||||
Two proto files in the same directory share the same `go_package`:
|
||||
|
||||
- `types.proto` — Defines shared message types (`User`).
|
||||
- `user.proto` — Defines the RPC service, importing `types.proto`.
|
||||
|
||||
Both files use the same `go_package` with a full module path:
|
||||
|
||||
```protobuf
|
||||
option go_package = "example.com/demo/pb";
|
||||
```
|
||||
|
||||
`user.proto` imports `types.proto` via:
|
||||
|
||||
```protobuf
|
||||
import "types.proto";
|
||||
```
|
||||
|
||||
## Generation Commands
|
||||
|
||||
First, initialize the output directory with a `go.mod`:
|
||||
|
||||
```bash
|
||||
mkdir -p output && cd output && go mod init example.com/demo && cd ..
|
||||
```
|
||||
|
||||
Then generate the code:
|
||||
|
||||
```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 .
|
||||
```
|
||||
|
||||
Generated directory structure:
|
||||
|
||||
```
|
||||
output/
|
||||
├── etc
|
||||
│ └── usersvc.yaml
|
||||
├── go.mod
|
||||
├── internal
|
||||
│ ├── config
|
||||
│ │ └── config.go
|
||||
│ ├── logic
|
||||
│ │ ├── createuserlogic.go
|
||||
│ │ └── getuserlogic.go
|
||||
│ ├── server
|
||||
│ │ └── userserviceserver.go
|
||||
│ └── svc
|
||||
│ └── servicecontext.go
|
||||
├── pb
|
||||
│ ├── types.pb.go
|
||||
│ ├── user.pb.go
|
||||
│ └── user_grpc.pb.go
|
||||
├── userservice
|
||||
│ └── userservice.go
|
||||
└── usersvc.go
|
||||
```
|
||||
|
||||
## Key Points
|
||||
|
||||
- Two proto files (`user.proto` and `types.proto`) share the same `go_package = "example.com/demo/pb"`, compiled into a single Go package.
|
||||
- `user.proto` imports `types.proto` via `import "types.proto"`.
|
||||
- When multiple proto files share the same `go_package`, they compile into a single Go package.
|
||||
- Only the proto file containing `service` definitions needs to be passed to `goctl rpc protoc`.
|
||||
- The imported proto is automatically compiled by protoc and resolved by goctl.
|
||||
11
tools/goctl/rpc/example/02-import-sibling/types.proto
Normal file
11
tools/goctl/rpc/example/02-import-sibling/types.proto
Normal file
@@ -0,0 +1,11 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package types;
|
||||
|
||||
option go_package = "example.com/demo/pb";
|
||||
|
||||
message User {
|
||||
string id = 1;
|
||||
string name = 2;
|
||||
int32 age = 3;
|
||||
}
|
||||
29
tools/goctl/rpc/example/02-import-sibling/user.proto
Normal file
29
tools/goctl/rpc/example/02-import-sibling/user.proto
Normal file
@@ -0,0 +1,29 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package usersvc;
|
||||
|
||||
option go_package = "example.com/demo/pb";
|
||||
|
||||
import "types.proto";
|
||||
|
||||
message GetUserReq {
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message GetUserReply {
|
||||
types.User user = 1;
|
||||
}
|
||||
|
||||
message CreateUserReq {
|
||||
string name = 1;
|
||||
int32 age = 2;
|
||||
}
|
||||
|
||||
message CreateUserReply {
|
||||
types.User user = 1;
|
||||
}
|
||||
|
||||
service UserService {
|
||||
rpc GetUser(GetUserReq) returns (GetUserReply);
|
||||
rpc CreateUser(CreateUserReq) returns (CreateUserReply);
|
||||
}
|
||||
82
tools/goctl/rpc/example/03-import-subdir/README-cn.md
Normal file
82
tools/goctl/rpc/example/03-import-subdir/README-cn.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# 示例 03:导入子目录中的 Proto 文件
|
||||
|
||||
本示例演示如何导入子目录中的 proto 文件。
|
||||
|
||||
## Proto 定义
|
||||
|
||||
两个 proto 文件有**不同**的 `go_package` 值:
|
||||
|
||||
- `order.proto` — 定义 `OrderService`,导入 `common/types.proto`。
|
||||
|
||||
```protobuf
|
||||
option go_package = "example.com/demo/pb";
|
||||
```
|
||||
|
||||
- `common/types.proto` — 定义可复用的分页和排序消息。
|
||||
|
||||
```protobuf
|
||||
option go_package = "example.com/demo/pb/common";
|
||||
```
|
||||
|
||||
`order.proto` 从子目录导入 `common/types.proto`:
|
||||
|
||||
```protobuf
|
||||
import "common/types.proto";
|
||||
```
|
||||
|
||||
注意两个文件的 `go_package` **不同**,因此会编译到不同的 Go 包中。
|
||||
|
||||
## 生成命令
|
||||
|
||||
首先,在输出目录中初始化 `go.mod`:
|
||||
|
||||
```bash
|
||||
mkdir -p output && cd output && go mod init example.com/demo && cd ..
|
||||
```
|
||||
|
||||
然后生成代码:
|
||||
|
||||
```bash
|
||||
goctl rpc protoc order.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 .
|
||||
```
|
||||
|
||||
生成的目录结构:
|
||||
|
||||
```
|
||||
output/
|
||||
├── etc
|
||||
│ └── ordersvc.yaml
|
||||
├── go.mod
|
||||
├── internal
|
||||
│ ├── config
|
||||
│ │ └── config.go
|
||||
│ ├── logic
|
||||
│ │ ├── getorderlogic.go
|
||||
│ │ └── listorderslogic.go
|
||||
│ ├── server
|
||||
│ │ └── orderserviceserver.go
|
||||
│ └── svc
|
||||
│ └── servicecontext.go
|
||||
├── orderservice
|
||||
│ └── orderservice.go
|
||||
├── ordersvc.go
|
||||
└── pb
|
||||
├── common
|
||||
│ └── types.pb.go
|
||||
├── order.pb.go
|
||||
└── order_grpc.pb.go
|
||||
```
|
||||
|
||||
## 要点说明
|
||||
|
||||
- 两个 proto 文件有**不同**的 `go_package` 值,编译到不同的 Go 包中(`pb/` 和 `pb/common/`)。
|
||||
- `order.proto` 从子目录导入 `common/types.proto`。
|
||||
- 当导入的 proto 文件有不同的 `go_package` 时,goctl 会自动生成跨包导入。
|
||||
- `-I .` 告诉 protoc 从当前目录开始搜索,使其能够找到 `common/types.proto`。
|
||||
82
tools/goctl/rpc/example/03-import-subdir/README.md
Normal file
82
tools/goctl/rpc/example/03-import-subdir/README.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Example 03: Importing Proto from a Subdirectory
|
||||
|
||||
This example demonstrates importing a proto file from a subdirectory.
|
||||
|
||||
## Proto Definition
|
||||
|
||||
Two proto files with **different** `go_package` values:
|
||||
|
||||
- `order.proto` — Defines the `OrderService`, imports `common/types.proto`.
|
||||
|
||||
```protobuf
|
||||
option go_package = "example.com/demo/pb";
|
||||
```
|
||||
|
||||
- `common/types.proto` — Defines reusable pagination and sorting messages.
|
||||
|
||||
```protobuf
|
||||
option go_package = "example.com/demo/pb/common";
|
||||
```
|
||||
|
||||
`order.proto` imports `common/types.proto` from a subdirectory:
|
||||
|
||||
```protobuf
|
||||
import "common/types.proto";
|
||||
```
|
||||
|
||||
Note that the two files have **different** `go_package` values, so they compile into separate Go packages.
|
||||
|
||||
## Generation Commands
|
||||
|
||||
First, initialize the output directory with a `go.mod`:
|
||||
|
||||
```bash
|
||||
mkdir -p output && cd output && go mod init example.com/demo && cd ..
|
||||
```
|
||||
|
||||
Then generate the code:
|
||||
|
||||
```bash
|
||||
goctl rpc protoc order.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 .
|
||||
```
|
||||
|
||||
Generated directory structure:
|
||||
|
||||
```
|
||||
output/
|
||||
├── etc
|
||||
│ └── ordersvc.yaml
|
||||
├── go.mod
|
||||
├── internal
|
||||
│ ├── config
|
||||
│ │ └── config.go
|
||||
│ ├── logic
|
||||
│ │ ├── getorderlogic.go
|
||||
│ │ └── listorderslogic.go
|
||||
│ ├── server
|
||||
│ │ └── orderserviceserver.go
|
||||
│ └── svc
|
||||
│ └── servicecontext.go
|
||||
├── orderservice
|
||||
│ └── orderservice.go
|
||||
├── ordersvc.go
|
||||
└── pb
|
||||
├── common
|
||||
│ └── types.pb.go
|
||||
├── order.pb.go
|
||||
└── order_grpc.pb.go
|
||||
```
|
||||
|
||||
## Key Points
|
||||
|
||||
- Two proto files have **different** `go_package` values, so they compile into separate Go packages (`pb/` and `pb/common/`).
|
||||
- `order.proto` imports `common/types.proto` from a subdirectory.
|
||||
- When imported protos have a different `go_package`, goctl automatically generates cross-package imports.
|
||||
- The `-I .` flag tells protoc to search from the current directory, enabling it to find `common/types.proto`.
|
||||
15
tools/goctl/rpc/example/03-import-subdir/common/types.proto
Normal file
15
tools/goctl/rpc/example/03-import-subdir/common/types.proto
Normal file
@@ -0,0 +1,15 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package common;
|
||||
|
||||
option go_package = "example.com/demo/pb/common";
|
||||
|
||||
message PageInfo {
|
||||
int32 page = 1;
|
||||
int32 size = 2;
|
||||
}
|
||||
|
||||
message SortInfo {
|
||||
string field = 1;
|
||||
string order = 2;
|
||||
}
|
||||
35
tools/goctl/rpc/example/03-import-subdir/order.proto
Normal file
35
tools/goctl/rpc/example/03-import-subdir/order.proto
Normal file
@@ -0,0 +1,35 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package ordersvc;
|
||||
|
||||
option go_package = "example.com/demo/pb";
|
||||
|
||||
import "common/types.proto";
|
||||
|
||||
message OrderItem {
|
||||
string id = 1;
|
||||
string name = 2;
|
||||
double price = 3;
|
||||
}
|
||||
|
||||
message ListOrdersReq {
|
||||
common.PageInfo page = 1;
|
||||
common.SortInfo sort = 2;
|
||||
}
|
||||
|
||||
message ListOrdersReply {
|
||||
repeated OrderItem orders = 1;
|
||||
}
|
||||
|
||||
message GetOrderReq {
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message GetOrderReply {
|
||||
OrderItem order = 1;
|
||||
}
|
||||
|
||||
service OrderService {
|
||||
rpc ListOrders(ListOrdersReq) returns (ListOrdersReply);
|
||||
rpc GetOrder(GetOrderReq) returns (GetOrderReply);
|
||||
}
|
||||
72
tools/goctl/rpc/example/04-transitive-import/README-cn.md
Normal file
72
tools/goctl/rpc/example/04-transitive-import/README-cn.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# 示例 04:传递性导入
|
||||
|
||||
本示例演示 proto 的传递性导入,即 A 导入 B,B 导入 C。
|
||||
|
||||
## Proto 定义
|
||||
|
||||
三个 proto 文件形成传递导入链,共享相同的 `go_package`:
|
||||
|
||||
```protobuf
|
||||
option go_package = "example.com/demo/pb";
|
||||
```
|
||||
|
||||
- `base.proto` — C 层:定义基础类型(`BaseResp`)。
|
||||
- `middleware.proto` — B 层:导入 `base.proto`,定义 `RequestMeta`。
|
||||
- `main.proto` — A 层:导入 `middleware.proto`,定义 `PingService`(入口文件)。
|
||||
|
||||
导入链:`main.proto` → `middleware.proto` → `base.proto`
|
||||
|
||||
## 生成命令
|
||||
|
||||
首先,在输出目录中初始化 `go.mod`:
|
||||
|
||||
```bash
|
||||
mkdir -p output && cd output && go mod init example.com/demo && cd ..
|
||||
```
|
||||
|
||||
然后生成代码:
|
||||
|
||||
```bash
|
||||
goctl rpc protoc main.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 .
|
||||
```
|
||||
|
||||
生成的目录结构:
|
||||
|
||||
```
|
||||
output/
|
||||
├── etc
|
||||
│ └── pingsvc.yaml
|
||||
├── go.mod
|
||||
├── internal
|
||||
│ ├── config
|
||||
│ │ └── config.go
|
||||
│ ├── logic
|
||||
│ │ └── pinglogic.go
|
||||
│ ├── server
|
||||
│ │ └── pingserviceserver.go
|
||||
│ └── svc
|
||||
│ └── servicecontext.go
|
||||
├── pb
|
||||
│ ├── base.pb.go
|
||||
│ ├── main.pb.go
|
||||
│ ├── main_grpc.pb.go
|
||||
│ └── middleware.pb.go
|
||||
├── pingservice
|
||||
│ └── pingservice.go
|
||||
└── pingsvc.go
|
||||
```
|
||||
|
||||
## 要点说明
|
||||
|
||||
- 三个 proto 文件(`base.proto` → `middleware.proto` → `main.proto`)形成传递导入链。
|
||||
- goctl 自动递归解析所有传递导入。
|
||||
- 三个文件共享相同的 `go_package = "example.com/demo/pb"`。
|
||||
- 只需指定入口 proto 文件,goctl 和 protoc 会自动处理其余部分。
|
||||
- 循环导入会被检测并报错(与 protoc 行为一致)。
|
||||
72
tools/goctl/rpc/example/04-transitive-import/README.md
Normal file
72
tools/goctl/rpc/example/04-transitive-import/README.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# Example 04: Transitive Imports
|
||||
|
||||
This example demonstrates transitive proto imports, where A imports B and B imports C.
|
||||
|
||||
## Proto Definition
|
||||
|
||||
Three proto files form a transitive import chain, all sharing the same `go_package`:
|
||||
|
||||
```protobuf
|
||||
option go_package = "example.com/demo/pb";
|
||||
```
|
||||
|
||||
- `base.proto` — Layer C: defines base types (`BaseResp`).
|
||||
- `middleware.proto` — Layer B: imports `base.proto`, defines `RequestMeta`.
|
||||
- `main.proto` — Layer A: imports `middleware.proto`, defines the `PingService` (entry point).
|
||||
|
||||
Import chain: `main.proto` → `middleware.proto` → `base.proto`
|
||||
|
||||
## Generation Commands
|
||||
|
||||
First, initialize the output directory with a `go.mod`:
|
||||
|
||||
```bash
|
||||
mkdir -p output && cd output && go mod init example.com/demo && cd ..
|
||||
```
|
||||
|
||||
Then generate the code:
|
||||
|
||||
```bash
|
||||
goctl rpc protoc main.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 .
|
||||
```
|
||||
|
||||
Generated directory structure:
|
||||
|
||||
```
|
||||
output/
|
||||
├── etc
|
||||
│ └── pingsvc.yaml
|
||||
├── go.mod
|
||||
├── internal
|
||||
│ ├── config
|
||||
│ │ └── config.go
|
||||
│ ├── logic
|
||||
│ │ └── pinglogic.go
|
||||
│ ├── server
|
||||
│ │ └── pingserviceserver.go
|
||||
│ └── svc
|
||||
│ └── servicecontext.go
|
||||
├── pb
|
||||
│ ├── base.pb.go
|
||||
│ ├── main.pb.go
|
||||
│ ├── main_grpc.pb.go
|
||||
│ └── middleware.pb.go
|
||||
├── pingservice
|
||||
│ └── pingservice.go
|
||||
└── pingsvc.go
|
||||
```
|
||||
|
||||
## Key Points
|
||||
|
||||
- Three proto files (`base.proto` → `middleware.proto` → `main.proto`) form a transitive import chain.
|
||||
- goctl recursively resolves all transitive imports automatically.
|
||||
- All three files share the same `go_package = "example.com/demo/pb"`.
|
||||
- You only need to specify the entry proto file — goctl and protoc handle the rest.
|
||||
- Circular imports are detected and will cause an error (same as protoc behavior).
|
||||
10
tools/goctl/rpc/example/04-transitive-import/base.proto
Normal file
10
tools/goctl/rpc/example/04-transitive-import/base.proto
Normal file
@@ -0,0 +1,10 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package base;
|
||||
|
||||
option go_package = "example.com/demo/pb";
|
||||
|
||||
message BaseResp {
|
||||
int32 code = 1;
|
||||
string msg = 2;
|
||||
}
|
||||
19
tools/goctl/rpc/example/04-transitive-import/main.proto
Normal file
19
tools/goctl/rpc/example/04-transitive-import/main.proto
Normal file
@@ -0,0 +1,19 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package pingsvc;
|
||||
|
||||
option go_package = "example.com/demo/pb";
|
||||
|
||||
import "middleware.proto";
|
||||
|
||||
message PingReq {
|
||||
middleware.RequestMeta meta = 1;
|
||||
}
|
||||
|
||||
message PingReply {
|
||||
string pong = 1;
|
||||
}
|
||||
|
||||
service PingService {
|
||||
rpc Ping(PingReq) returns (PingReply);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package middleware;
|
||||
|
||||
option go_package = "example.com/demo/pb";
|
||||
|
||||
import "base.proto";
|
||||
|
||||
message RequestMeta {
|
||||
string trace_id = 1;
|
||||
base.BaseResp base = 2;
|
||||
}
|
||||
80
tools/goctl/rpc/example/05-multiple-services/README-cn.md
Normal file
80
tools/goctl/rpc/example/05-multiple-services/README-cn.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# 示例 05:多服务模式(`--multiple`)
|
||||
|
||||
本示例演示从一个 proto 文件生成多个 RPC 服务。
|
||||
|
||||
## Proto 定义
|
||||
|
||||
两个 proto 文件共享相同的 `go_package`:
|
||||
|
||||
```protobuf
|
||||
option go_package = "example.com/demo/pb";
|
||||
```
|
||||
|
||||
- `shared.proto` — 定义共享消息类型(`Meta`)。
|
||||
- `multi.proto` — 定义了**两个**服务:`SearchService` 和 `NotifyService`。
|
||||
|
||||
当 proto 文件包含多个 `service` 块时,必须使用 `-m`(或 `--multiple`)标志。
|
||||
|
||||
## 生成命令
|
||||
|
||||
首先,在输出目录中初始化 `go.mod`:
|
||||
|
||||
```bash
|
||||
mkdir -p output && cd output && go mod init example.com/demo && cd ..
|
||||
```
|
||||
|
||||
然后使用 `-m` 标志生成代码:
|
||||
|
||||
```bash
|
||||
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
|
||||
```
|
||||
|
||||
生成的目录结构:
|
||||
|
||||
```
|
||||
output/
|
||||
├── client
|
||||
│ ├── notifyservice
|
||||
│ │ └── notifyservice.go
|
||||
│ └── searchservice
|
||||
│ └── searchservice.go
|
||||
├── etc
|
||||
│ └── multisvc.yaml
|
||||
├── go.mod
|
||||
├── internal
|
||||
│ ├── config
|
||||
│ │ └── config.go
|
||||
│ ├── logic
|
||||
│ │ ├── notifyservice
|
||||
│ │ │ └── notifylogic.go
|
||||
│ │ └── searchservice
|
||||
│ │ └── searchlogic.go
|
||||
│ ├── server
|
||||
│ │ ├── notifyservice
|
||||
│ │ │ └── notifyserviceserver.go
|
||||
│ │ └── searchservice
|
||||
│ │ └── searchserviceserver.go
|
||||
│ └── svc
|
||||
│ └── servicecontext.go
|
||||
├── multisvc.go
|
||||
└── pb
|
||||
├── multi.pb.go
|
||||
├── multi_grpc.pb.go
|
||||
└── shared.pb.go
|
||||
```
|
||||
|
||||
## 要点说明
|
||||
|
||||
- `-m`(或 `--multiple`)标志启用多服务模式。
|
||||
- 多服务模式下,`client/` 包含按服务名分组的子目录;`logic/` 和 `server/` 也按服务名分组。
|
||||
- 两个服务共享一个入口文件(`multisvc.go`)和配置。
|
||||
- 不使用 `--multiple` 时,goctl 只允许每个 proto 文件有一个 `service` 块。
|
||||
- 所有服务共享同一个 `config.go` 和 `servicecontext.go`。
|
||||
80
tools/goctl/rpc/example/05-multiple-services/README.md
Normal file
80
tools/goctl/rpc/example/05-multiple-services/README.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# Example 05: Multiple Services (`--multiple`)
|
||||
|
||||
This example demonstrates generating multiple RPC services from a single proto file.
|
||||
|
||||
## Proto Definition
|
||||
|
||||
Two proto files share the same `go_package`:
|
||||
|
||||
```protobuf
|
||||
option go_package = "example.com/demo/pb";
|
||||
```
|
||||
|
||||
- `shared.proto` — Defines shared message types (`Meta`).
|
||||
- `multi.proto` — Defines **two** services: `SearchService` and `NotifyService`.
|
||||
|
||||
The `-m` (or `--multiple`) flag is required when a proto file contains more than one `service` block.
|
||||
|
||||
## Generation Commands
|
||||
|
||||
First, initialize the output directory with a `go.mod`:
|
||||
|
||||
```bash
|
||||
mkdir -p output && cd output && go mod init example.com/demo && cd ..
|
||||
```
|
||||
|
||||
Then generate the code with the `-m` flag:
|
||||
|
||||
```bash
|
||||
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
|
||||
```
|
||||
|
||||
Generated directory structure:
|
||||
|
||||
```
|
||||
output/
|
||||
├── client
|
||||
│ ├── notifyservice
|
||||
│ │ └── notifyservice.go
|
||||
│ └── searchservice
|
||||
│ └── searchservice.go
|
||||
├── etc
|
||||
│ └── multisvc.yaml
|
||||
├── go.mod
|
||||
├── internal
|
||||
│ ├── config
|
||||
│ │ └── config.go
|
||||
│ ├── logic
|
||||
│ │ ├── notifyservice
|
||||
│ │ │ └── notifylogic.go
|
||||
│ │ └── searchservice
|
||||
│ │ └── searchlogic.go
|
||||
│ ├── server
|
||||
│ │ ├── notifyservice
|
||||
│ │ │ └── notifyserviceserver.go
|
||||
│ │ └── searchservice
|
||||
│ │ └── searchserviceserver.go
|
||||
│ └── svc
|
||||
│ └── servicecontext.go
|
||||
├── multisvc.go
|
||||
└── pb
|
||||
├── multi.pb.go
|
||||
├── multi_grpc.pb.go
|
||||
└── shared.pb.go
|
||||
```
|
||||
|
||||
## Key Points
|
||||
|
||||
- The `-m` (or `--multiple`) flag enables multiple-service mode.
|
||||
- In multiple mode, `client/` contains per-service subdirectories; `logic/` and `server/` are also grouped by service name.
|
||||
- Both services share a single entry point (`multisvc.go`) and config.
|
||||
- Without `--multiple`, goctl only allows one `service` block per proto file.
|
||||
- All services share the same `config.go` and `servicecontext.go`.
|
||||
33
tools/goctl/rpc/example/05-multiple-services/multi.proto
Normal file
33
tools/goctl/rpc/example/05-multiple-services/multi.proto
Normal file
@@ -0,0 +1,33 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package multisvc;
|
||||
|
||||
option go_package = "example.com/demo/pb";
|
||||
|
||||
import "shared.proto";
|
||||
|
||||
message SearchReq {
|
||||
shared.Meta meta = 1;
|
||||
string keyword = 2;
|
||||
}
|
||||
|
||||
message SearchReply {
|
||||
repeated string items = 1;
|
||||
}
|
||||
|
||||
message NotifyReq {
|
||||
shared.Meta meta = 1;
|
||||
string message = 2;
|
||||
}
|
||||
|
||||
message NotifyReply {
|
||||
bool ok = 1;
|
||||
}
|
||||
|
||||
service SearchService {
|
||||
rpc Search(SearchReq) returns (SearchReply);
|
||||
}
|
||||
|
||||
service NotifyService {
|
||||
rpc Notify(NotifyReq) returns (NotifyReply);
|
||||
}
|
||||
10
tools/goctl/rpc/example/05-multiple-services/shared.proto
Normal file
10
tools/goctl/rpc/example/05-multiple-services/shared.proto
Normal file
@@ -0,0 +1,10 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package shared;
|
||||
|
||||
option go_package = "example.com/demo/pb";
|
||||
|
||||
message Meta {
|
||||
string trace_id = 1;
|
||||
string version = 2;
|
||||
}
|
||||
65
tools/goctl/rpc/example/06-wellknown-types/README-cn.md
Normal file
65
tools/goctl/rpc/example/06-wellknown-types/README-cn.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# 示例 06:知名类型
|
||||
|
||||
本示例演示如何使用 Google protobuf 知名类型(`Timestamp`、`Duration`、`Any`)作为消息字段。
|
||||
|
||||
## Proto 定义
|
||||
|
||||
`events.proto` 使用 `google.protobuf.Timestamp` 作为消息字段类型。
|
||||
|
||||
`go_package` 使用完整的模块路径:
|
||||
|
||||
```protobuf
|
||||
option go_package = "example.com/demo/pb";
|
||||
```
|
||||
|
||||
## 生成命令
|
||||
|
||||
首先,在输出目录中初始化 `go.mod`:
|
||||
|
||||
```bash
|
||||
mkdir -p output && cd output && go mod init example.com/demo && cd ..
|
||||
```
|
||||
|
||||
然后生成代码:
|
||||
|
||||
```bash
|
||||
goctl rpc protoc events.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 .
|
||||
```
|
||||
|
||||
生成的目录结构:
|
||||
|
||||
```
|
||||
output/
|
||||
├── etc
|
||||
│ └── eventsvc.yaml
|
||||
├── eventservice
|
||||
│ └── eventservice.go
|
||||
├── eventsvc.go
|
||||
├── go.mod
|
||||
├── internal
|
||||
│ ├── config
|
||||
│ │ └── config.go
|
||||
│ ├── logic
|
||||
│ │ ├── createeventlogic.go
|
||||
│ │ └── listeventslogic.go
|
||||
│ ├── server
|
||||
│ │ └── eventserviceserver.go
|
||||
│ └── svc
|
||||
│ └── servicecontext.go
|
||||
└── pb
|
||||
├── events.pb.go
|
||||
└── events_grpc.pb.go
|
||||
```
|
||||
|
||||
## 要点说明
|
||||
|
||||
- 使用 Google 知名类型(`google.protobuf.Timestamp`、`google.protobuf.Duration`、`google.protobuf.Any`)作为消息字段。
|
||||
- goctl 自动将知名类型映射到 Go 导入包(`timestamppb`、`durationpb`、`anypb` 等)。
|
||||
- 如果 protoc 已正确安装,知名类型无需额外的 `--proto_path`。
|
||||
65
tools/goctl/rpc/example/06-wellknown-types/README.md
Normal file
65
tools/goctl/rpc/example/06-wellknown-types/README.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Example 06: Well-Known Types
|
||||
|
||||
This example demonstrates using Google protobuf well-known types (`Timestamp`, `Duration`, `Any`) as message fields.
|
||||
|
||||
## Proto Definition
|
||||
|
||||
`events.proto` uses `google.protobuf.Timestamp` as a message field type.
|
||||
|
||||
The `go_package` uses a full module path:
|
||||
|
||||
```protobuf
|
||||
option go_package = "example.com/demo/pb";
|
||||
```
|
||||
|
||||
## Generation Commands
|
||||
|
||||
First, initialize the output directory with a `go.mod`:
|
||||
|
||||
```bash
|
||||
mkdir -p output && cd output && go mod init example.com/demo && cd ..
|
||||
```
|
||||
|
||||
Then generate the code:
|
||||
|
||||
```bash
|
||||
goctl rpc protoc events.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 .
|
||||
```
|
||||
|
||||
Generated directory structure:
|
||||
|
||||
```
|
||||
output/
|
||||
├── etc
|
||||
│ └── eventsvc.yaml
|
||||
├── eventservice
|
||||
│ └── eventservice.go
|
||||
├── eventsvc.go
|
||||
├── go.mod
|
||||
├── internal
|
||||
│ ├── config
|
||||
│ │ └── config.go
|
||||
│ ├── logic
|
||||
│ │ ├── createeventlogic.go
|
||||
│ │ └── listeventslogic.go
|
||||
│ ├── server
|
||||
│ │ └── eventserviceserver.go
|
||||
│ └── svc
|
||||
│ └── servicecontext.go
|
||||
└── pb
|
||||
├── events.pb.go
|
||||
└── events_grpc.pb.go
|
||||
```
|
||||
|
||||
## Key Points
|
||||
|
||||
- Uses Google well-known types (`google.protobuf.Timestamp`, `google.protobuf.Duration`, `google.protobuf.Any`) as message fields.
|
||||
- goctl automatically maps well-known types to Go imports (`timestamppb`, `durationpb`, `anypb`, etc.).
|
||||
- No extra `--proto_path` needed for well-known types if protoc is properly installed.
|
||||
35
tools/goctl/rpc/example/06-wellknown-types/events.proto
Normal file
35
tools/goctl/rpc/example/06-wellknown-types/events.proto
Normal file
@@ -0,0 +1,35 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package eventsvc;
|
||||
|
||||
option go_package = "example.com/demo/pb";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
message Event {
|
||||
string id = 1;
|
||||
string name = 2;
|
||||
google.protobuf.Timestamp created_at = 3;
|
||||
}
|
||||
|
||||
message CreateEventReq {
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
message CreateEventReply {
|
||||
Event event = 1;
|
||||
}
|
||||
|
||||
message ListEventsReq {
|
||||
int32 page = 1;
|
||||
int32 size = 2;
|
||||
}
|
||||
|
||||
message ListEventsReply {
|
||||
repeated Event events = 1;
|
||||
}
|
||||
|
||||
service EventService {
|
||||
rpc CreateEvent(CreateEventReq) returns (CreateEventReply);
|
||||
rpc ListEvents(ListEventsReq) returns (ListEventsReply);
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
# 示例 07:外部 Proto — 相同 `go_package`
|
||||
|
||||
本示例演示从外部目录导入 proto 文件,且两个文件共享**相同**的 `go_package`。
|
||||
|
||||
## Proto 定义
|
||||
|
||||
`service.proto` 和 `ext.proto` 使用相同的 `go_package`:
|
||||
|
||||
```protobuf
|
||||
option go_package = "example.com/demo/pb";
|
||||
```
|
||||
|
||||
源码布局:
|
||||
|
||||
```
|
||||
07-external-proto-same-pkg/
|
||||
├── ext_protos
|
||||
│ └── ext.proto # 外部 proto(go_package = "example.com/demo/pb")
|
||||
├── service.proto # 服务定义(go_package = "example.com/demo/pb")
|
||||
├── README.md
|
||||
└── README-cn.md
|
||||
```
|
||||
|
||||
- `ext.proto` 位于独立目录(`ext_protos/`),但与 `service.proto` 有相同的 `go_package`。
|
||||
- `service.proto` 导入 `ext.proto`,使用 `ext.ExtReq` / `ext.ExtReply` 作为 RPC 类型。
|
||||
|
||||
## 生成命令
|
||||
|
||||
首先,在输出目录中初始化 `go.mod`:
|
||||
|
||||
```bash
|
||||
mkdir -p output && cd output && go mod init example.com/demo && cd ..
|
||||
```
|
||||
|
||||
然后生成代码(注意 `-I ./ext_protos`):
|
||||
|
||||
```bash
|
||||
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 ./ext_protos
|
||||
```
|
||||
|
||||
生成的目录结构:
|
||||
|
||||
```
|
||||
output/
|
||||
├── etc
|
||||
│ └── svc.yaml
|
||||
├── go.mod
|
||||
├── internal
|
||||
│ ├── config
|
||||
│ │ └── config.go
|
||||
│ ├── logic
|
||||
│ │ └── querylogic.go
|
||||
│ ├── server
|
||||
│ │ └── queryserviceserver.go
|
||||
│ └── svc
|
||||
│ └── servicecontext.go
|
||||
├── pb
|
||||
│ ├── ext.pb.go
|
||||
│ ├── service.pb.go
|
||||
│ └── service_grpc.pb.go
|
||||
├── queryservice
|
||||
│ └── queryservice.go
|
||||
└── svc.go
|
||||
```
|
||||
|
||||
## 要点说明
|
||||
|
||||
- `ext.proto` 位于独立目录(`ext_protos/`),但与 `service.proto` 有相同的 `go_package`。
|
||||
- 使用 `-I ./ext_protos` 将外部目录添加到 proto 搜索路径。
|
||||
- 当外部 proto 有**相同**的 `go_package` 时,所有类型合并到一个 Go 包中——无需跨包导入。
|
||||
77
tools/goctl/rpc/example/07-external-proto-same-pkg/README.md
Normal file
77
tools/goctl/rpc/example/07-external-proto-same-pkg/README.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# Example 07: External Proto — Same `go_package`
|
||||
|
||||
This example demonstrates importing proto files from an external directory where both files share the **same** `go_package`.
|
||||
|
||||
## Proto Definition
|
||||
|
||||
Both `service.proto` and `ext.proto` use the same `go_package`:
|
||||
|
||||
```protobuf
|
||||
option go_package = "example.com/demo/pb";
|
||||
```
|
||||
|
||||
Source layout:
|
||||
|
||||
```
|
||||
07-external-proto-same-pkg/
|
||||
├── ext_protos
|
||||
│ └── ext.proto # External proto (go_package = "example.com/demo/pb")
|
||||
├── service.proto # Service definition (go_package = "example.com/demo/pb")
|
||||
├── README.md
|
||||
└── README-cn.md
|
||||
```
|
||||
|
||||
- `ext.proto` lives in a separate directory (`ext_protos/`), but has the same `go_package` as `service.proto`.
|
||||
- `service.proto` imports `ext.proto` and uses `ext.ExtReq` / `ext.ExtReply` as RPC types.
|
||||
|
||||
## Generation Commands
|
||||
|
||||
First, initialize the output directory with a `go.mod`:
|
||||
|
||||
```bash
|
||||
mkdir -p output && cd output && go mod init example.com/demo && cd ..
|
||||
```
|
||||
|
||||
Then generate the code (note `-I ./ext_protos`):
|
||||
|
||||
```bash
|
||||
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 ./ext_protos
|
||||
```
|
||||
|
||||
Generated directory structure:
|
||||
|
||||
```
|
||||
output/
|
||||
├── etc
|
||||
│ └── svc.yaml
|
||||
├── go.mod
|
||||
├── internal
|
||||
│ ├── config
|
||||
│ │ └── config.go
|
||||
│ ├── logic
|
||||
│ │ └── querylogic.go
|
||||
│ ├── server
|
||||
│ │ └── queryserviceserver.go
|
||||
│ └── svc
|
||||
│ └── servicecontext.go
|
||||
├── pb
|
||||
│ ├── ext.pb.go
|
||||
│ ├── service.pb.go
|
||||
│ └── service_grpc.pb.go
|
||||
├── queryservice
|
||||
│ └── queryservice.go
|
||||
└── svc.go
|
||||
```
|
||||
|
||||
## Key Points
|
||||
|
||||
- `ext.proto` lives in a separate directory (`ext_protos/`), but has the same `go_package` as `service.proto`.
|
||||
- Use `-I ./ext_protos` to add the external directory to the proto search path.
|
||||
- When the external proto has the **same** `go_package`, all types merge into one Go package — no cross-package imports are needed.
|
||||
@@ -0,0 +1,14 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package ext;
|
||||
|
||||
option go_package = "example.com/demo/pb";
|
||||
|
||||
message ExtReq {
|
||||
string key = 1;
|
||||
}
|
||||
|
||||
message ExtReply {
|
||||
string value = 1;
|
||||
int32 code = 2;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package svc;
|
||||
|
||||
option go_package = "example.com/demo/pb";
|
||||
|
||||
import "ext.proto";
|
||||
|
||||
service QueryService {
|
||||
rpc Query(ext.ExtReq) returns (ext.ExtReply);
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
# 示例 08:外部 Proto — 不同 `go_package`
|
||||
|
||||
本示例演示从外部目录导入 proto 文件,且文件具有**不同**的 `go_package` 值,需要在生成的 Go 代码中进行跨包导入。
|
||||
|
||||
## Proto 定义
|
||||
|
||||
proto 文件使用不同的 `go_package` 值:
|
||||
|
||||
- `service.proto`:`go_package = "example.com/demo/pb"`
|
||||
- `ext_protos/common/types.proto`:`go_package = "example.com/demo/pb/common"`
|
||||
|
||||
源码布局:
|
||||
|
||||
```
|
||||
08-external-proto-diff-pkg/
|
||||
├── ext_protos
|
||||
│ └── common
|
||||
│ └── types.proto # 外部 proto(go_package = "example.com/demo/pb/common")
|
||||
├── service.proto # 服务定义(go_package = "example.com/demo/pb")
|
||||
├── README.md
|
||||
└── README-cn.md
|
||||
```
|
||||
|
||||
- `types.proto` 的 `go_package = "example.com/demo/pb/common"` — **不同**的 Go 包。
|
||||
- `service.proto` 直接使用 `common.ExtReq` / `common.ExtReply` 作为 RPC 参数类型。
|
||||
|
||||
## 生成命令
|
||||
|
||||
首先,在输出目录中初始化 `go.mod`:
|
||||
|
||||
```bash
|
||||
mkdir -p output && cd output && go mod init example.com/demo && cd ..
|
||||
```
|
||||
|
||||
然后生成代码(注意 `-I ./ext_protos`):
|
||||
|
||||
```bash
|
||||
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 ./ext_protos
|
||||
```
|
||||
|
||||
生成的目录结构:
|
||||
|
||||
```
|
||||
output/
|
||||
├── dataservice
|
||||
│ └── dataservice.go
|
||||
├── etc
|
||||
│ └── svc.yaml
|
||||
├── go.mod
|
||||
├── internal
|
||||
│ ├── config
|
||||
│ │ └── config.go
|
||||
│ ├── logic
|
||||
│ │ └── fetchlogic.go
|
||||
│ ├── server
|
||||
│ │ └── dataserviceserver.go
|
||||
│ └── svc
|
||||
│ └── servicecontext.go
|
||||
├── pb
|
||||
│ ├── common
|
||||
│ │ └── types.pb.go
|
||||
│ ├── service.pb.go
|
||||
│ └── service_grpc.pb.go
|
||||
└── svc.go
|
||||
```
|
||||
|
||||
## 要点说明
|
||||
|
||||
- 当外部 proto 有**不同**的 `go_package` 时,goctl 会自动生成跨包 Go 导入。
|
||||
- goctl 通过解析导入 proto 的 `go_package` 选项,将 proto 包名(如 `common`)映射到正确的 Go 导入路径。
|
||||
- `service.proto` 直接使用 `common.ExtReq` / `common.ExtReply` 作为 RPC 参数类型。
|
||||
78
tools/goctl/rpc/example/08-external-proto-diff-pkg/README.md
Normal file
78
tools/goctl/rpc/example/08-external-proto-diff-pkg/README.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# Example 08: External Proto — Different `go_package`
|
||||
|
||||
This example demonstrates importing proto files from an external directory where the files have **different** `go_package` values, requiring cross-package imports in the generated Go code.
|
||||
|
||||
## Proto Definition
|
||||
|
||||
The proto files use different `go_package` values:
|
||||
|
||||
- `service.proto`: `go_package = "example.com/demo/pb"`
|
||||
- `ext_protos/common/types.proto`: `go_package = "example.com/demo/pb/common"`
|
||||
|
||||
Source layout:
|
||||
|
||||
```
|
||||
08-external-proto-diff-pkg/
|
||||
├── ext_protos
|
||||
│ └── common
|
||||
│ └── types.proto # External proto (go_package = "example.com/demo/pb/common")
|
||||
├── service.proto # Service definition (go_package = "example.com/demo/pb")
|
||||
├── README.md
|
||||
└── README-cn.md
|
||||
```
|
||||
|
||||
- `types.proto` has `go_package = "example.com/demo/pb/common"` — a **different** Go package.
|
||||
- `service.proto` uses `common.ExtReq` / `common.ExtReply` directly as RPC parameter types.
|
||||
|
||||
## Generation Commands
|
||||
|
||||
First, initialize the output directory with a `go.mod`:
|
||||
|
||||
```bash
|
||||
mkdir -p output && cd output && go mod init example.com/demo && cd ..
|
||||
```
|
||||
|
||||
Then generate the code (note `-I ./ext_protos`):
|
||||
|
||||
```bash
|
||||
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 ./ext_protos
|
||||
```
|
||||
|
||||
Generated directory structure:
|
||||
|
||||
```
|
||||
output/
|
||||
├── dataservice
|
||||
│ └── dataservice.go
|
||||
├── etc
|
||||
│ └── svc.yaml
|
||||
├── go.mod
|
||||
├── internal
|
||||
│ ├── config
|
||||
│ │ └── config.go
|
||||
│ ├── logic
|
||||
│ │ └── fetchlogic.go
|
||||
│ ├── server
|
||||
│ │ └── dataserviceserver.go
|
||||
│ └── svc
|
||||
│ └── servicecontext.go
|
||||
├── pb
|
||||
│ ├── common
|
||||
│ │ └── types.pb.go
|
||||
│ ├── service.pb.go
|
||||
│ └── service_grpc.pb.go
|
||||
└── svc.go
|
||||
```
|
||||
|
||||
## Key Points
|
||||
|
||||
- When the external proto has a **different** `go_package`, goctl generates cross-package Go imports automatically.
|
||||
- goctl resolves the proto package name (e.g., `common`) to the correct Go import path by parsing the imported proto's `go_package` option.
|
||||
- `service.proto` uses `common.ExtReq` / `common.ExtReply` directly as RPC parameter types.
|
||||
@@ -0,0 +1,15 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package common;
|
||||
|
||||
option go_package = "example.com/demo/pb/common";
|
||||
|
||||
message ExtReq {
|
||||
string key = 1;
|
||||
string source = 2;
|
||||
}
|
||||
|
||||
message ExtReply {
|
||||
string value = 1;
|
||||
int32 code = 2;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package svc;
|
||||
|
||||
option go_package = "example.com/demo/pb";
|
||||
|
||||
import "common/types.proto";
|
||||
|
||||
service DataService {
|
||||
rpc Fetch(common.ExtReq) returns (common.ExtReply);
|
||||
}
|
||||
65
tools/goctl/rpc/example/09-google-types-as-rpc/README-cn.md
Normal file
65
tools/goctl/rpc/example/09-google-types-as-rpc/README-cn.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# 示例 09:Google 类型作为 RPC 参数
|
||||
|
||||
本示例演示将 Google protobuf 知名类型**直接**用作 RPC 请求或响应类型(而不仅仅是消息字段)。
|
||||
|
||||
## Proto 定义
|
||||
|
||||
`service.proto` 使用 `google.protobuf.Empty` 和 `google.protobuf.Timestamp` 直接作为 RPC 请求/响应类型。
|
||||
|
||||
`go_package` 使用完整的模块路径:
|
||||
|
||||
```protobuf
|
||||
option go_package = "example.com/demo/pb";
|
||||
```
|
||||
|
||||
## 生成命令
|
||||
|
||||
首先,在输出目录中初始化 `go.mod`:
|
||||
|
||||
```bash
|
||||
mkdir -p output && cd output && go mod init example.com/demo && cd ..
|
||||
```
|
||||
|
||||
然后生成代码:
|
||||
|
||||
```bash
|
||||
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 .
|
||||
```
|
||||
|
||||
生成的目录结构:
|
||||
|
||||
```
|
||||
output/
|
||||
├── etc
|
||||
│ └── healthsvc.yaml
|
||||
├── go.mod
|
||||
├── healthservice
|
||||
│ └── healthservice.go
|
||||
├── healthsvc.go
|
||||
├── internal
|
||||
│ ├── config
|
||||
│ │ └── config.go
|
||||
│ ├── logic
|
||||
│ │ ├── gettimelogic.go
|
||||
│ │ └── pinglogic.go
|
||||
│ ├── server
|
||||
│ │ └── healthserviceserver.go
|
||||
│ └── svc
|
||||
│ └── servicecontext.go
|
||||
└── pb
|
||||
├── service.pb.go
|
||||
└── service_grpc.pb.go
|
||||
```
|
||||
|
||||
## 要点说明
|
||||
|
||||
- 使用 Google 知名类型(`google.protobuf.Empty`、`google.protobuf.Timestamp`)直接作为 RPC 请求/响应类型(不仅仅是消息字段)。
|
||||
- goctl 正确将其映射到 Go 类型(`emptypb.Empty`、`timestamppb.Timestamp`)并生成正确的导入。
|
||||
- 这与示例 06 不同,示例 06 中知名类型用作消息字段。
|
||||
65
tools/goctl/rpc/example/09-google-types-as-rpc/README.md
Normal file
65
tools/goctl/rpc/example/09-google-types-as-rpc/README.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Example 09: Google Types as RPC Parameters
|
||||
|
||||
This example demonstrates using Google protobuf well-known types **directly** as RPC request or response types (not just as message fields).
|
||||
|
||||
## Proto Definition
|
||||
|
||||
`service.proto` uses `google.protobuf.Empty` and `google.protobuf.Timestamp` directly as RPC request/response types.
|
||||
|
||||
The `go_package` uses a full module path:
|
||||
|
||||
```protobuf
|
||||
option go_package = "example.com/demo/pb";
|
||||
```
|
||||
|
||||
## Generation Commands
|
||||
|
||||
First, initialize the output directory with a `go.mod`:
|
||||
|
||||
```bash
|
||||
mkdir -p output && cd output && go mod init example.com/demo && cd ..
|
||||
```
|
||||
|
||||
Then generate the code:
|
||||
|
||||
```bash
|
||||
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 .
|
||||
```
|
||||
|
||||
Generated directory structure:
|
||||
|
||||
```
|
||||
output/
|
||||
├── etc
|
||||
│ └── healthsvc.yaml
|
||||
├── go.mod
|
||||
├── healthservice
|
||||
│ └── healthservice.go
|
||||
├── healthsvc.go
|
||||
├── internal
|
||||
│ ├── config
|
||||
│ │ └── config.go
|
||||
│ ├── logic
|
||||
│ │ ├── gettimelogic.go
|
||||
│ │ └── pinglogic.go
|
||||
│ ├── server
|
||||
│ │ └── healthserviceserver.go
|
||||
│ └── svc
|
||||
│ └── servicecontext.go
|
||||
└── pb
|
||||
├── service.pb.go
|
||||
└── service_grpc.pb.go
|
||||
```
|
||||
|
||||
## Key Points
|
||||
|
||||
- Uses Google well-known types (`google.protobuf.Empty`, `google.protobuf.Timestamp`) directly as RPC request/response types (not just message fields).
|
||||
- goctl correctly maps these to Go types (`emptypb.Empty`, `timestamppb.Timestamp`) and generates proper imports.
|
||||
- This differs from Example 06 where well-known types are used as message fields.
|
||||
19
tools/goctl/rpc/example/09-google-types-as-rpc/service.proto
Normal file
19
tools/goctl/rpc/example/09-google-types-as-rpc/service.proto
Normal file
@@ -0,0 +1,19 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package healthsvc;
|
||||
|
||||
option go_package = "example.com/demo/pb";
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
message HealthCheckReq {
|
||||
string service = 1;
|
||||
}
|
||||
|
||||
service HealthService {
|
||||
// Ping returns empty — useful for health checks with no response body.
|
||||
rpc Ping(HealthCheckReq) returns (google.protobuf.Empty);
|
||||
// GetTime returns a Timestamp directly as the response type.
|
||||
rpc GetTime(HealthCheckReq) returns (google.protobuf.Timestamp);
|
||||
}
|
||||
66
tools/goctl/rpc/example/10-streaming/README-cn.md
Normal file
66
tools/goctl/rpc/example/10-streaming/README-cn.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# 示例 10:流式 RPC
|
||||
|
||||
本示例演示 gRPC 的三种流式通信模式:服务端流、客户端流和双向流。
|
||||
|
||||
## Proto 定义
|
||||
|
||||
`stream.proto` 定义了三个 RPC 方法,演示每种流式模式。
|
||||
|
||||
`go_package` 使用完整的模块路径:
|
||||
|
||||
```protobuf
|
||||
option go_package = "example.com/demo/pb";
|
||||
```
|
||||
|
||||
## 生成命令
|
||||
|
||||
首先,在输出目录中初始化 `go.mod`:
|
||||
|
||||
```bash
|
||||
mkdir -p output && cd output && go mod init example.com/demo && cd ..
|
||||
```
|
||||
|
||||
然后生成代码:
|
||||
|
||||
```bash
|
||||
goctl rpc protoc stream.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 .
|
||||
```
|
||||
|
||||
生成的目录结构:
|
||||
|
||||
```
|
||||
output/
|
||||
├── etc
|
||||
│ └── streamsvc.yaml
|
||||
├── go.mod
|
||||
├── internal
|
||||
│ ├── config
|
||||
│ │ └── config.go
|
||||
│ ├── logic
|
||||
│ │ ├── bidistreamlogic.go
|
||||
│ │ ├── clientstreamlogic.go
|
||||
│ │ └── serverstreamlogic.go
|
||||
│ ├── server
|
||||
│ │ └── streamserviceserver.go
|
||||
│ └── svc
|
||||
│ └── servicecontext.go
|
||||
├── pb
|
||||
│ ├── stream.pb.go
|
||||
│ └── stream_grpc.pb.go
|
||||
├── streamservice
|
||||
│ └── streamservice.go
|
||||
└── streamsvc.go
|
||||
```
|
||||
|
||||
## 要点说明
|
||||
|
||||
- 支持三种流式模式:服务端流(响应带 `stream`)、客户端流(请求带 `stream`)和双向流(两端都带 `stream`)。
|
||||
- goctl 为每个流式 RPC 方法生成独立的逻辑文件。
|
||||
- 流式客户端代码不会自动生成,需直接使用 gRPC 客户端。
|
||||
66
tools/goctl/rpc/example/10-streaming/README.md
Normal file
66
tools/goctl/rpc/example/10-streaming/README.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# Example 10: Streaming RPC
|
||||
|
||||
This example demonstrates all three gRPC streaming patterns: server streaming, client streaming, and bidirectional streaming.
|
||||
|
||||
## Proto Definition
|
||||
|
||||
`stream.proto` defines three RPC methods demonstrating each streaming pattern.
|
||||
|
||||
The `go_package` uses a full module path:
|
||||
|
||||
```protobuf
|
||||
option go_package = "example.com/demo/pb";
|
||||
```
|
||||
|
||||
## Generation Commands
|
||||
|
||||
First, initialize the output directory with a `go.mod`:
|
||||
|
||||
```bash
|
||||
mkdir -p output && cd output && go mod init example.com/demo && cd ..
|
||||
```
|
||||
|
||||
Then generate the code:
|
||||
|
||||
```bash
|
||||
goctl rpc protoc stream.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 .
|
||||
```
|
||||
|
||||
Generated directory structure:
|
||||
|
||||
```
|
||||
output/
|
||||
├── etc
|
||||
│ └── streamsvc.yaml
|
||||
├── go.mod
|
||||
├── internal
|
||||
│ ├── config
|
||||
│ │ └── config.go
|
||||
│ ├── logic
|
||||
│ │ ├── bidistreamlogic.go
|
||||
│ │ ├── clientstreamlogic.go
|
||||
│ │ └── serverstreamlogic.go
|
||||
│ ├── server
|
||||
│ │ └── streamserviceserver.go
|
||||
│ └── svc
|
||||
│ └── servicecontext.go
|
||||
├── pb
|
||||
│ ├── stream.pb.go
|
||||
│ └── stream_grpc.pb.go
|
||||
├── streamservice
|
||||
│ └── streamservice.go
|
||||
└── streamsvc.go
|
||||
```
|
||||
|
||||
## Key Points
|
||||
|
||||
- Supports three streaming patterns: server streaming (`stream` on response), client streaming (`stream` on request), and bidirectional streaming (`stream` on both).
|
||||
- goctl generates separate logic files for each streaming RPC method.
|
||||
- Streaming client code is not auto-generated; use the gRPC client directly.
|
||||
24
tools/goctl/rpc/example/10-streaming/stream.proto
Normal file
24
tools/goctl/rpc/example/10-streaming/stream.proto
Normal file
@@ -0,0 +1,24 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package streamsvc;
|
||||
|
||||
option go_package = "example.com/demo/pb";
|
||||
|
||||
message StreamReq {
|
||||
string input = 1;
|
||||
}
|
||||
|
||||
message StreamReply {
|
||||
string output = 1;
|
||||
}
|
||||
|
||||
service StreamService {
|
||||
// ServerStream: client sends one request, server returns a stream of responses.
|
||||
rpc ServerStream(StreamReq) returns (stream StreamReply);
|
||||
|
||||
// ClientStream: client sends a stream of requests, server returns one response.
|
||||
rpc ClientStream(stream StreamReq) returns (StreamReply);
|
||||
|
||||
// BidiStream: both client and server send streams of messages.
|
||||
rpc BidiStream(stream StreamReq) returns (stream StreamReply);
|
||||
}
|
||||
93
tools/goctl/rpc/example/README.md
Normal file
93
tools/goctl/rpc/example/README.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# RPC Examples
|
||||
|
||||
This directory contains complete examples for all `goctl rpc` code generation scenarios.
|
||||
|
||||
Each example includes:
|
||||
- `.proto` source files
|
||||
- `README.md` (English) and `README-cn.md` (中文) documentation
|
||||
|
||||
## Examples
|
||||
|
||||
| # | Directory | Scenario | Key Flags |
|
||||
|---|-----------|----------|-----------|
|
||||
| 01 | [01-basic](01-basic/) | Basic single service, no imports | — |
|
||||
| 02 | [02-import-sibling](02-import-sibling/) | Import sibling proto file | `--proto_path=.` |
|
||||
| 03 | [03-import-subdir](03-import-subdir/) | Import proto from subdirectory | `--proto_path=.` |
|
||||
| 04 | [04-transitive-import](04-transitive-import/) | Transitive imports (A → B → C) | `--proto_path=.` |
|
||||
| 05 | [05-multiple-services](05-multiple-services/) | Multiple services in one proto | `--multiple` |
|
||||
| 06 | [06-wellknown-types](06-wellknown-types/) | Google well-known types in messages | `--proto_path=$PROTOC_INCLUDE` |
|
||||
| 07 | [07-external-proto-same-pkg](07-external-proto-same-pkg/) | External proto, same `go_package` | `-I ./ext_protos` |
|
||||
| 08 | [08-external-proto-diff-pkg](08-external-proto-diff-pkg/) | External proto, different `go_package` | `-I ./ext_protos` |
|
||||
| 09 | [09-google-types-as-rpc](09-google-types-as-rpc/) | Google types as RPC parameters | `--proto_path=$PROTOC_INCLUDE` |
|
||||
| 10 | [10-streaming](10-streaming/) | Server/client/bidirectional streaming | — |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Go](https://go.dev/) 1.22+
|
||||
- [protoc](https://github.com/protocolbuffers/protobuf/releases) (Protocol Buffers compiler)
|
||||
- [protoc-gen-go](https://pkg.go.dev/google.golang.org/protobuf/cmd/protoc-gen-go) and [protoc-gen-go-grpc](https://pkg.go.dev/google.golang.org/grpc/cmd/protoc-gen-go-grpc)
|
||||
- [goctl](https://github.com/zeromicro/go-zero/tree/master/tools/goctl)
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Install protoc plugins
|
||||
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
|
||||
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
|
||||
|
||||
# Try the basic example
|
||||
cd 01-basic
|
||||
mkdir -p output && cd output && go mod init example.com/demo && cd ..
|
||||
goctl rpc protoc greeter.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 .
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# RPC 示例
|
||||
|
||||
本目录包含所有 `goctl rpc` 代码生成场景的完整示例。
|
||||
|
||||
每个示例包含:
|
||||
- `.proto` 源文件
|
||||
- `README.md`(英文)和 `README-cn.md`(中文)文档
|
||||
|
||||
## 示例列表
|
||||
|
||||
| # | 目录 | 场景 | 关键标志 |
|
||||
|---|------|------|---------|
|
||||
| 01 | [01-basic](01-basic/) | 基础单服务,无导入 | — |
|
||||
| 02 | [02-import-sibling](02-import-sibling/) | 导入同级 proto 文件 | `--proto_path=.` |
|
||||
| 03 | [03-import-subdir](03-import-subdir/) | 导入子目录中的 proto | `--proto_path=.` |
|
||||
| 04 | [04-transitive-import](04-transitive-import/) | 传递性导入(A → B → C) | `--proto_path=.` |
|
||||
| 05 | [05-multiple-services](05-multiple-services/) | 单 proto 多服务 | `--multiple` |
|
||||
| 06 | [06-wellknown-types](06-wellknown-types/) | 消息中使用 Google 标准类型 | `--proto_path=$PROTOC_INCLUDE` |
|
||||
| 07 | [07-external-proto-same-pkg](07-external-proto-same-pkg/) | 外部 proto,相同 `go_package` | `-I ./ext_protos` |
|
||||
| 08 | [08-external-proto-diff-pkg](08-external-proto-diff-pkg/) | 外部 proto,不同 `go_package` | `-I ./ext_protos` |
|
||||
| 09 | [09-google-types-as-rpc](09-google-types-as-rpc/) | Google 类型作为 RPC 参数 | `--proto_path=$PROTOC_INCLUDE` |
|
||||
| 10 | [10-streaming](10-streaming/) | 服务端/客户端/双向流 | — |
|
||||
|
||||
## 前置条件
|
||||
|
||||
- [Go](https://go.dev/) 1.22+
|
||||
- [protoc](https://github.com/protocolbuffers/protobuf/releases)(Protocol Buffers 编译器)
|
||||
- [protoc-gen-go](https://pkg.go.dev/google.golang.org/protobuf/cmd/protoc-gen-go) 和 [protoc-gen-go-grpc](https://pkg.go.dev/google.golang.org/grpc/cmd/protoc-gen-go-grpc)
|
||||
- [goctl](https://github.com/zeromicro/go-zero/tree/master/tools/goctl)
|
||||
|
||||
## 快速开始
|
||||
|
||||
```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
|
||||
|
||||
# 试试基础示例
|
||||
cd 01-basic
|
||||
mkdir -p output && cd output && go mod init example.com/demo && cd ..
|
||||
goctl rpc protoc greeter.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 .
|
||||
```
|
||||
Reference in New Issue
Block a user