Grpc go
Skill Mattakushi432/Claude-Code-Skills-Custom-DevTools-Pack/plugins/devtools-pack/skills/grpc-go
When to activate: gRPC in Go, protobuf, server/client setup, interceptors, streaming, metadata, health checksFrom its SKILL.md
npx -y skills add Mattakushi432/Claude-Code-Skills-Custom-DevTools-Pack --skill grpc-goAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
4.6 KB, ~1.1k tokens by cl100k_base, as published. Nobody here has run it
gRPC in Go
Proto Definition
// api/user/v1/user.proto
syntax = "proto3";
package user.v1;
option go_package = "github.com/myorg/myapp/gen/user/v1;userv1";
service UserService {
rpc GetUser(GetUserRequest) returns (GetUserResponse);
rpc ListUsers(ListUsersRequest) returns (stream UserResponse);
rpc CreateUser(CreateUserRequest) returns (CreateUserResponse);
}
message GetUserRequest { string id = 1; }
message GetUserResponse { User user = 1; }
message User {
string id = 1;
string email = 2;
string name = 3;
}
# Generate Go code
protoc --go_out=gen --go_opt=paths=source_relative \
--go-grpc_out=gen --go-grpc_opt=paths=source_relative \
api/user/v1/user.proto
Server Implementation
package main
import (
"context"
"net"
pb "github.com/myorg/myapp/gen/user/v1"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
type userServer struct {
pb.UnimplementedUserServiceServer // forward-compat
repo UserRepository
}
func (s *userServer) GetUser(ctx context.Context, req *pb.GetUserRequest) (*pb.GetUserResponse, error) {
user, err := s.repo.FindByID(ctx, req.Id)
if err != nil {
if errors.Is(err, ErrNotFound) {
return nil, status.Errorf(codes.NotFound, "user %s not found", req.Id)
}
return nil, status.Errorf(codes.Internal, "internal error: %v", err)
}
return &pb.GetUserResponse{User: toProto(user)}, nil
}
func (s *userServer) ListUsers(req *pb.ListUsersRequest, stream pb.UserService_ListUsersServer) error {
users, err := s.repo.List(stream.Context())
if err != nil { return status.Errorf(codes.Internal, "%v", err) }
for _, u := range users {
if err := stream.Send(toProto(u)); err != nil { return err }
}
return nil
}
func main() {
lis, _ := net.Listen("tcp", ":50051")
srv := grpc.NewServer(
grpc.ChainUnaryInterceptor(loggingInterceptor, authInterceptor),
)
pb.RegisterUserServiceServer(srv, &userServer{repo: NewPGRepo(db)})
srv.Serve(lis)
}
Interceptors (Middleware)
func loggingInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
start := time.Now()
resp, err := handler(ctx, req)
log.Printf("method=%s duration=%s err=%v", info.FullMethod, time.Since(start), err)
return resp, err
}
func authInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
md, ok := metadata.FromIncomingContext(ctx)
if !ok { return nil, status.Error(codes.Unauthenticated, "missing metadata") }
tokens := md.Get("authorization")
if len(tokens) == 0 || !validateToken(tokens[0]) {
return nil, status.Error(codes.Unauthenticated, "invalid token")
}
return handler(ctx, req)
}
Client Setup
func NewUserClient(addr string) (pb.UserServiceClient, error) {
conn, err := grpc.NewClient(addr,
grpc.WithTransportCredentials(insecure.NewCredentials()), // use TLS in prod
grpc.WithChainUnaryInterceptor(clientAuthInterceptor),
)
if err != nil { return nil, err }
return pb.NewUserServiceClient(conn), nil
}
func clientAuthInterceptor(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
ctx = metadata.AppendToOutgoingContext(ctx, "authorization", "Bearer "+getToken())
return invoker(ctx, method, req, reply, cc, opts...)
}
gRPC Health Check
import "google.golang.org/grpc/health/grpc_health_v1"
import "google.golang.org/grpc/health"
healthSrv := health.NewServer()
grpc_health_v1.RegisterHealthServer(grpcServer, healthSrv)
healthSrv.SetServingStatus("user.v1.UserService", grpc_health_v1.HealthCheckResponse_SERVING)
Common Anti-Patterns
- Not embedding
Unimplemented*Server— breaks when new RPCs are added to the proto - Returning raw Go errors — always wrap with
status.Errorf(codes.X, ...) - Blocking stream without context check — check
stream.Context().Done()in loops - Ignoring connection draining — call
grpc.GracefulStop()on shutdown, notStop() - Hardcoded TLS-less credentials in prod — use
credentials.NewTLS(tlsConfig)in production
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.