mirror of
https://github.com/zeromicro/go-zero.git
synced 2026-05-10 00:20:00 +08:00
316 lines
10 KiB
Markdown
316 lines
10 KiB
Markdown
# goctl rpc — RPC Code Generation
|
|
|
|
English | [中文](README-cn.md)
|
|
|
|
goctl rpc is the RPC service code generation module of the `goctl` scaffold. It generates a complete zRPC service from `.proto` files. You only need to write the proto definition and business logic — all boilerplate code is generated automatically.
|
|
|
|
## Features
|
|
|
|
- **protoc compatible**: Fully compatible with protoc, all protoc arguments are passed through
|
|
- **External proto imports**: Cross-directory and cross-package proto imports with automatic transitive dependency resolution
|
|
- **Multiple services**: Define multiple services in a single proto file, auto-grouped by service name
|
|
- **Streaming support**: Server streaming, client streaming, and bidirectional streaming
|
|
- **Google well-known types**: Automatic recognition of `google.protobuf.*` types with correct Go imports
|
|
- **Client generation**: Auto-generated RPC client wrapper code
|
|
|
|
## Prerequisites
|
|
|
|
```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
|
|
```
|
|
|
|
## Quick Start
|
|
|
|
### Method 1: Create a Service Instantly
|
|
|
|
```bash
|
|
goctl rpc new greeter
|
|
```
|
|
|
|
Generates a complete project structure:
|
|
|
|
```
|
|
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 a Proto File
|
|
|
|
1. Generate a proto template:
|
|
|
|
```bash
|
|
goctl rpc template -o=user.proto
|
|
```
|
|
|
|
2. Initialize the output directory and generate service code:
|
|
|
|
```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 .
|
|
```
|
|
|
|
---
|
|
|
|
## Command Reference
|
|
|
|
### `goctl rpc protoc`
|
|
|
|
Generate zRPC service code from a `.proto` file.
|
|
|
|
```bash
|
|
goctl rpc protoc <proto_file> [flags]
|
|
```
|
|
|
|
**Examples:**
|
|
|
|
```bash
|
|
# Basic usage
|
|
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 .
|
|
|
|
# Multiple services mode
|
|
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
|
|
|
|
# Import external protos
|
|
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
|
|
|
|
# Use Google well-known types
|
|
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 .
|
|
```
|
|
|
|
**Flags:**
|
|
|
|
| Flag | Short | Type | Default | Description |
|
|
|------|-------|------|---------|-------------|
|
|
| `--zrpc_out` | | string | **required** | Output directory for zRPC service code |
|
|
| `--go_out` | | string | **required** | Output directory for protoc Go code |
|
|
| `--go-grpc_out` | | string | **required** | Output directory for protoc gRPC code |
|
|
| `--go_opt` | | string | | Options for protoc-gen-go (e.g., `module=example.com/demo`) |
|
|
| `--go-grpc_opt` | | string | | Options for protoc-gen-go-grpc (e.g., `module=example.com/demo`) |
|
|
| `--proto_path` | `-I` | string[] | | Proto import search directories (repeatable) |
|
|
| `--multiple` | `-m` | bool | `false` | Multiple services mode |
|
|
| `--client` | `-c` | bool | `true` | Generate RPC client code |
|
|
| `--style` | | string | `gozero` | File naming style |
|
|
| `--module` | | string | | Custom Go module name |
|
|
| `--name-from-filename` | | bool | `false` | Use filename instead of package name for service naming |
|
|
| `--verbose` | `-v` | bool | `false` | Enable verbose logging |
|
|
| `--home` | | string | | goctl template directory |
|
|
| `--remote` | | string | | Remote template Git repository URL |
|
|
| `--branch` | | string | | Remote template branch |
|
|
|
|
### `goctl rpc new`
|
|
|
|
Quickly create a complete RPC service project.
|
|
|
|
```bash
|
|
goctl rpc new <service_name> [flags]
|
|
```
|
|
|
|
**Flags:**
|
|
|
|
| Flag | Short | Type | Default | Description |
|
|
|------|-------|------|---------|-------------|
|
|
| `--style` | | string | `gozero` | File naming style |
|
|
| `--client` | `-c` | bool | `true` | Generate RPC client code |
|
|
| `--module` | | string | | Custom Go module name |
|
|
| `--verbose` | `-v` | bool | `false` | Enable verbose logging |
|
|
| `--idea` | | bool | `false` | Generate IDE project marker |
|
|
| `--name-from-filename` | | bool | `false` | Use filename instead of package name for service naming |
|
|
| `--home` | | string | | goctl template directory |
|
|
| `--remote` | | string | | Remote template Git repository URL |
|
|
| `--branch` | | string | | Remote template branch |
|
|
|
|
### `goctl rpc template`
|
|
|
|
Generate a proto file template.
|
|
|
|
```bash
|
|
goctl rpc template -o=<output_file> [flags]
|
|
```
|
|
|
|
**Flags:**
|
|
|
|
| Flag | Type | Description |
|
|
|------|------|-------------|
|
|
| `-o` | string | Output file path (required) |
|
|
| `--home` | string | goctl template directory |
|
|
| `--remote` | string | Remote template Git repository URL |
|
|
| `--branch` | string | Remote template branch |
|
|
|
|
---
|
|
|
|
## Feature Details
|
|
|
|
### Multiple Services Mode (`--multiple`)
|
|
|
|
When a proto file contains multiple `service` definitions, the `--multiple` flag is required.
|
|
|
|
```protobuf
|
|
service SearchService {
|
|
rpc Search(SearchReq) returns (SearchReply);
|
|
}
|
|
|
|
service NotifyService {
|
|
rpc Notify(NotifyReq) returns (NotifyReply);
|
|
}
|
|
```
|
|
|
|
**Directory differences with `--multiple`:**
|
|
|
|
| Feature | Default mode | `--multiple` mode |
|
|
|---------|-------------|-------------------|
|
|
| Services per proto | Exactly 1 | 1 or more |
|
|
| Client directory | Named after service | Fixed `client/` directory |
|
|
| Code organization | Flat structure | Grouped by service name |
|
|
|
|
**`--multiple=false` (default) directory structure:**
|
|
|
|
```
|
|
output/
|
|
├── greeterclient/
|
|
│ └── greeter.go
|
|
├── internal/
|
|
│ ├── logic/
|
|
│ │ └── sayhellologic.go
|
|
│ └── server/
|
|
│ └── greeterserver.go
|
|
└── ...
|
|
```
|
|
|
|
**`--multiple=true` directory structure:**
|
|
|
|
```
|
|
output/
|
|
├── client/
|
|
│ ├── searchservice/
|
|
│ │ └── searchservice.go
|
|
│ └── notifyservice/
|
|
│ └── notifyservice.go
|
|
├── internal/
|
|
│ ├── logic/
|
|
│ │ ├── searchservice/
|
|
│ │ │ └── searchlogic.go
|
|
│ │ └── notifyservice/
|
|
│ │ └── notifylogic.go
|
|
│ └── server/
|
|
│ ├── searchservice/
|
|
│ │ └── searchserviceserver.go
|
|
│ └── notifyservice/
|
|
│ └── notifyserviceserver.go
|
|
└── ...
|
|
```
|
|
|
|
### External Proto Imports (`--proto_path`)
|
|
|
|
Use `-I` / `--proto_path` to specify additional proto search directories. Supported scenarios:
|
|
|
|
- **Same-directory import**: `import "types.proto";`
|
|
- **Subdirectory import**: `import "common/types.proto";`
|
|
- **External directory import**: Proto files outside the project
|
|
- **Transitive imports**: A imports B, B imports C — goctl resolves recursively
|
|
- **Cross-package imports**: Different `go_package` values generate correct Go imports automatically
|
|
|
|
```bash
|
|
# Search multiple directories for proto files
|
|
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
|
|
```
|
|
|
|
### Service Naming
|
|
|
|
By default, the service name is derived from the proto **package name** (e.g., `package user;` → service name `user`). This allows multiple proto files to share the same package:
|
|
|
|
```
|
|
protos/
|
|
├── user_base.proto # package user;
|
|
├── user_auth.proto # package user;
|
|
└── user_profile.proto # package user;
|
|
```
|
|
|
|
All three files generate into a single `user` service.
|
|
|
|
To use the proto filename for naming (legacy behavior), add the `--name-from-filename` flag.
|
|
|
|
### Streaming RPC
|
|
|
|
All three gRPC streaming patterns are supported:
|
|
|
|
```protobuf
|
|
service StreamService {
|
|
rpc ServerStream(Req) returns (stream Reply); // Server streaming
|
|
rpc ClientStream(stream Req) returns (Reply); // Client streaming
|
|
rpc BidiStream(stream Req) returns (stream Reply); // Bidirectional streaming
|
|
}
|
|
```
|
|
|
|
### Google Well-Known Types
|
|
|
|
goctl automatically recognizes and handles Google protobuf well-known types:
|
|
|
|
| Proto Type | Go Type |
|
|
|-----------|---------|
|
|
| `google.protobuf.Empty` | `emptypb.Empty` |
|
|
| `google.protobuf.Timestamp` | `timestamppb.Timestamp` |
|
|
| `google.protobuf.Duration` | `durationpb.Duration` |
|
|
| `google.protobuf.Any` | `anypb.Any` |
|
|
| `google.protobuf.Struct` | `structpb.Struct` |
|
|
| `google.protobuf.FieldMask` | `fieldmaskpb.FieldMask` |
|
|
| `google.protobuf.*Value` | `wrapperspb.*Value` |
|
|
|
|
These types can be used directly as RPC parameter types — goctl generates the correct imports automatically.
|
|
|
|
---
|
|
|
|
## Examples
|
|
|
|
See the [example/](example/) directory for 10 complete examples covering all generation scenarios.
|
|
|
|
| # | Example | Scenario |
|
|
|---|---------|----------|
|
|
| 01 | [Basic service](example/01-basic/) | Single service, no imports |
|
|
| 02 | [Sibling import](example/02-import-sibling/) | Import from same directory |
|
|
| 03 | [Subdirectory import](example/03-import-subdir/) | Import from subdirectory |
|
|
| 04 | [Transitive import](example/04-transitive-import/) | A → B → C dependency chain |
|
|
| 05 | [Multiple services](example/05-multiple-services/) | `--multiple` mode |
|
|
| 06 | [Well-known types](example/06-wellknown-types/) | Timestamp etc. in messages |
|
|
| 07 | [External proto (same pkg)](example/07-external-proto-same-pkg/) | External proto, same go_package |
|
|
| 08 | [External proto (diff pkg)](example/08-external-proto-diff-pkg/) | External proto, different go_package |
|
|
| 09 | [Google types as params](example/09-google-types-as-rpc/) | Empty/Timestamp as RPC parameters |
|
|
| 10 | [Streaming](example/10-streaming/) | Server/client/bidirectional streaming |
|