README
¶
goctl rpc — RPC Code Generation
English | 中文
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
# 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
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
- Generate a proto template:
goctl rpc template -o=user.proto
- Initialize the output directory and generate service code:
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.
goctl rpc protoc <proto_file> [flags]
Examples:
# 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.
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.
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.
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_packagevalues generate correct Go imports automatically
# 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:
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/ directory for 10 complete examples covering all generation scenarios.
| # | Example | Scenario |
|---|---|---|
| 01 | Basic service | Single service, no imports |
| 02 | Sibling import | Import from same directory |
| 03 | Subdirectory import | Import from subdirectory |
| 04 | Transitive import | A → B → C dependency chain |
| 05 | Multiple services | --multiple mode |
| 06 | Well-known types | Timestamp etc. in messages |
| 07 | External proto (same pkg) | External proto, same go_package |
| 08 | External proto (diff pkg) | External proto, different go_package |
| 09 | Google types as params | Empty/Timestamp as RPC parameters |
| 10 | Streaming | Server/client/bidirectional streaming |
Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( // Cmd describes a rpc command. Cmd = cobrax.NewCommand("rpc", cobrax.WithRunE(func(command *cobra.Command, strings []string) error { return cli.RPCTemplate(true) })) )
Functions ¶
This section is empty.
Types ¶
This section is empty.