
Golang Grpc
- 394 installs
- 63 repo stars
- Updated July 18, 2026
- bobmatnyc/claude-mpm-skills
Build and maintain Go gRPC servers and clients with protobuf contracts, interceptors, streaming, and production-ready error handling.
About
Go gRPC skill for implementing production RPC backends with protobuf schemas, server and client stubs, streaming handlers, interceptors, and robust error handling for microservice APIs and internal service integrations.
- Defines protobuf service contracts
- Implements unary and streaming handlers
- Configures interceptors and metadata
- Covers client generation and error mapping
Golang Grpc by the numbers
- 394 all-time installs (skills.sh)
- Ranked #26 of 98 Go skills by installs in the Skillselion catalog
- Data as of Aug 1, 2026 (Skillselion catalog sync)
npx skills add https://github.com/bobmatnyc/claude-mpm-skills --skill golang-grpcAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 394 |
|---|---|
| repo stars | ★ 63 |
| Last updated | July 18, 2026 |
| Repository | bobmatnyc/claude-mpm-skills ↗ |
What it does
Build and maintain Go gRPC servers and clients with protobuf contracts, interceptors, streaming, and production-ready error handling.
Files
Go gRPC (Production)
Overview
gRPC provides strongly-typed RPC APIs backed by Protocol Buffers, with first-class streaming support and excellent performance for service-to-service communication. This skill focuses on production defaults: versioned protos, deadlines, error codes, interceptors, health checks, TLS, and testability.
Quick Start
1) Define a versioned protobuf API
✅ Correct: versioned package
// proto/users/v1/users.proto
syntax = "proto3";
package users.v1;
option go_package = "example.com/myapp/gen/users/v1;usersv1";
service UsersService {
rpc GetUser(GetUserRequest) returns (GetUserResponse);
rpc ListUsers(ListUsersRequest) returns (stream User);
}
message GetUserRequest { string id = 1; }
message GetUserResponse { User user = 1; }
message ListUsersRequest { int32 page_size = 1; string page_token = 2; }
message User {
string id = 1;
string email = 2;
string display_name = 3;
}❌ Wrong: unversioned package (hard to evolve)
package users;2) Generate Go code
Install generators:
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latestGenerate:
protoc -I proto \
--go_out=./gen --go_opt=paths=source_relative \
--go-grpc_out=./gen --go-grpc_opt=paths=source_relative \
proto/users/v1/users.proto3) Implement server with deadlines and status codes
✅ Correct: validate + map errors to gRPC codes
package usersvc
import (
"context"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
usersv1 "example.com/myapp/gen/users/v1"
)
type Service struct {
usersv1.UnimplementedUsersServiceServer
Repo Repo
}
type Repo interface {
GetUser(ctx context.Context, id string) (User, error)
}
type User struct {
ID, Email, DisplayName string
}
func (s *Service) GetUser(ctx context.Context, req *usersv1.GetUserRequest) (*usersv1.GetUserResponse, error) {
if req.GetId() == "" {
return nil, status.Error(codes.InvalidArgument, "id is required")
}
u, err := s.Repo.GetUser(ctx, req.GetId())
if err != nil {
if err == ErrNotFound {
return nil, status.Error(codes.NotFound, "user not found")
}
return nil, status.Error(codes.Internal, "internal error")
}
return &usersv1.GetUserResponse{
User: &usersv1.User{
Id: u.ID,
Email: u.Email,
DisplayName: u.DisplayName,
},
}, nil
}❌ Wrong: return raw errors (clients lose code semantics)
return nil, errors.New("user not found")Core Concepts
Deadlines and cancellation
Make every call bounded; enforce server-side timeouts for expensive handlers.
✅ Correct: require deadline
if _, ok := ctx.Deadline(); !ok {
return nil, status.Error(codes.InvalidArgument, "deadline required")
}Metadata
Use metadata for auth/session correlation, not for primary request data.
✅ Correct: read auth token from metadata
md, _ := metadata.FromIncomingContext(ctx)
auth := ""
if vals := md.Get("authorization"); len(vals) > 0 {
auth = vals[0]
}Interceptors (Middleware)
Use interceptors for cross-cutting concerns: auth, logging, metrics, tracing, request IDs.
✅ Correct: unary interceptor with request ID
func unaryRequestID() grpc.UnaryServerInterceptor {
return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
id := uuid.NewString()
ctx = context.WithValue(ctx, requestIDKey{}, id)
resp, err := handler(ctx, req)
return resp, err
}
}Streaming patterns
Server streaming (paginate or stream results)
✅ Correct: stop on ctx.Done()
func (s *Service) ListUsers(req *usersv1.ListUsersRequest, stream usersv1.UsersService_ListUsersServer) error {
users, err := s.Repo.ListUsers(stream.Context(), int(req.GetPageSize()))
if err != nil {
return status.Error(codes.Internal, "internal error")
}
for _, u := range users {
select {
case <-stream.Context().Done():
return stream.Context().Err()
default:
}
if err := stream.Send(&usersv1.User{
Id: u.ID,
Email: u.Email,
DisplayName: u.DisplayName,
}); err != nil {
return err
}
}
return nil
}Unary vs streaming decision
- Use unary for single request/response and simple retries.
- Use server streaming for large result sets or continuous updates.
- Use client streaming for bulk uploads with one final response.
- Use bidirectional streaming for interactive protocols.
Production Hardening
Health checks and reflection
Add health service; enable reflection only in non-production environments.
✅ Correct: health + conditional reflection
hs := health.NewServer()
grpc_health_v1.RegisterHealthServer(s, hs)
if env != "production" {
reflection.Register(s)
}Graceful shutdown
Prefer GracefulStop with a deadline.
✅ Correct: graceful stop
stopped := make(chan struct{})
go func() {
grpcServer.GracefulStop()
close(stopped)
}()
select {
case <-stopped:
case <-time.After(10 * time.Second):
grpcServer.Stop()
}TLS
Use TLS (or mTLS) in production; avoid insecure credentials outside local dev.
✅ Correct: server TLS
creds, err := credentials.NewServerTLSFromFile("server.crt", "server.key")
if err != nil { return err }
grpcServer := grpc.NewServer(grpc.Creds(creds))Testing (bufconn)
Test gRPC handlers without opening real sockets using bufconn.
✅ Correct: in-memory gRPC test server
const bufSize = 1024 * 1024
lis := bufconn.Listen(bufSize)
srv := grpc.NewServer()
usersv1.RegisterUsersServiceServer(srv, &Service{Repo: repo})
go func() { _ = srv.Serve(lis) }()
ctx := context.Background()
conn, err := grpc.DialContext(
ctx,
"bufnet",
grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) { return lis.Dial() }),
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
if err != nil { t.Fatal(err) }
defer conn.Close()
client := usersv1.NewUsersServiceClient(conn)
resp, err := client.GetUser(ctx, &usersv1.GetUserRequest{Id: "1"})
_ = resp
_ = errAnti-Patterns
- Ignore deadlines: unbounded handlers cause tail latency and resource exhaustion.
- Return string errors: map domain errors to
codes.*withstatus.Errororstatus.Errorf.
- Stream without backpressure: stop on
ctx.Done()and handleSenderrors.
- Expose reflection in production: treat reflection as a discovery surface.
Troubleshooting
Symptom: clients see UNKNOWN errors
Actions:
- Return
status.Error(codes.X, "...")instead of raw errors. - Wrap domain errors into typed errors, then map to gRPC codes.
Symptom: slow/hanging requests
Actions:
- Require deadlines and propagate
ctxto downstream calls. - Add server-side timeouts and bounded concurrency in repositories.
Symptom: flaky streaming
Actions:
- Stop streaming on
ctx.Done()and handlestream.Senderrors. - Avoid buffering entire result sets before sending.
Resources
- gRPC Go: https://github.com/grpc/grpc-go
- Protobuf Go: https://pkg.go.dev/google.golang.org/protobuf
- gRPC error codes: https://grpc.io/docs/guides/error/
{
"name": "golang-grpc",
"version": "1.0.0",
"category": "toolchain",
"toolchain": "golang",
"tags": [
"golang",
"grpc",
"protobuf",
"microservices",
"streaming",
"interceptors",
"authentication",
"observability",
"testing"
],
"entry_point_tokens": 160,
"full_tokens": 2077,
"related_skills": [
"golang-concurrency-patterns",
"golang-http-frameworks",
"golang-testing-strategies",
"golang-observability-opentelemetry",
"api-design-patterns"
],
"author": "Claude MPM Team",
"license": "MIT",
"requires": [],
"repository": "https://github.com/bobmatnyc/claude-mpm-skills",
"created": "2025-12-17",
"updated": "2025-12-17"
}