Create an RPC Service
Create an RPC Service
Section titled “Create an RPC Service”This guide creates a user RPC service that an API gateway can call over gRPC.
Prerequisites
Section titled “Prerequisites”protocinstalledprotoc-gen-goandprotoc-gen-go-grpcinstalled
Not installed? See Install protoc.
Step 1 — Scaffold the Service
Section titled “Step 1 — Scaffold the Service”goctl rpc new usercd usergo mod tidyGoctl creates a .proto file and the full service skeleton:
user/├── etc/│ └── user.yaml├── internal/│ ├── config/config.go│ ├── logic/│ │ └── getuserlogic.go # ← implement this│ ├── server/userserver.go # gRPC server adapter│ └── svc/servicecontext.go├── user/│ └── user.pb.go # generated protobuf types│ └── user_grpc.pb.go # generated gRPC stubs├── user.go # entrypoint└── user.proto # source of truthStep 2 — The Generated Proto
Section titled “Step 2 — The Generated Proto”Open user.proto:
syntax = "proto3";
package user;option go_package = "./user";
service User { rpc GetUser(GetUserRequest) returns (GetUserResponse);}
message GetUserRequest { int64 id = 1;}
message GetUserResponse { int64 id = 1; string name = 2;}Step 3 — Implement Business Logic
Section titled “Step 3 — Implement Business Logic”Edit internal/logic/getuserlogic.go:
func (l *GetUserLogic) GetUser(in *user.GetUserRequest) (*user.GetUserResponse, error) { // In production: query your DB via l.svcCtx return &user.GetUserResponse{ Id: in.Id, Name: "alice", }, nil}Step 4 — Configure and Run
Section titled “Step 4 — Configure and Run”Open etc/user.yaml — the default port is 8080:
Name: user.rpcListenOn: 0.0.0.0:8080Run the RPC server:
go run user.go# Starting rpc server at 0.0.0.0:8080...Step 5 — Call It from an API Service
Section titled “Step 5 — Call It from an API Service”Generate the RPC client stub that your API gateway will use:
goctl rpc protoc user.proto \ --go_out=./user \ --go-grpc_out=./user \ --zrpc_out=./clientIn your API service’s servicecontext.go:
UserRpc userclient.User // inject the generated clientThen call it from a logic file:
resp, err := l.svcCtx.UserRpc.GetUser(l.ctx, &user.GetUserRequest{Id: 1})go-zero handles connection pooling, load balancing, and circuit breaking automatically.
Regenerating After Proto Changes
Section titled “Regenerating After Proto Changes”goctl rpc protoc user.proto \ --go_out=./user \ --go-grpc_out=./user \ --zrpc_out=.