Claude-skill-registry go-microservices
Production-ready Go microservices patterns including Gin, Echo, gRPC, clean architecture, dependency injection, error handling, middleware, testing, Docker containerization, Kubernetes deployment, distributed tracing, observability with Prometheus, high-performance APIs, concurrent processing, database integration with GORM, Redis caching, message queues, and cloud-native best practices.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/go-microservices" ~/.claude/skills/majiayu000-claude-skill-registry-go-microservices && rm -rf "$T"
manifest:
skills/data/go-microservices/SKILL.mdsource content
Go Microservices Development Skill
Purpose
Build high-performance, scalable microservices in Go following clean architecture, industry best practices, and cloud-native patterns for production AWS deployments.
When to Use This Skill
Auto-activates when working with:
- Go microservice development
- gRPC service implementation
- RESTful APIs with Gin/Echo
- High-performance backend services
- Concurrent data processing
- Docker containerization
- Kubernetes deployments
- Distributed systems
Core Principles
1. Clean Architecture (Hexagonal)
Handlers (HTTP/gRPC) → Use Cases (Business Logic) → Repositories (Data Access) → External Systems
2. Dependency Injection
- Wire dependencies at startup
- Use interfaces for testability
- Avoid global state
3. Concurrency
- Leverage goroutines and channels
- Use context for cancellation
- Implement worker pools
4. Error Handling
- Wrap errors with context
- Use custom error types
- Log with structured fields
Quick Start Examples
Clean Architecture Project Structure
service/ ├── cmd/ │ └── api/ │ └── main.go # Application entry point ├── internal/ │ ├── domain/ # Business entities │ │ ├── user.go │ │ └── errors.go │ ├── usecase/ # Business logic │ │ └── user_usecase.go │ ├── repository/ # Data access │ │ └── user_repository.go │ ├── handler/ # HTTP/gRPC handlers │ │ ├── http/ │ │ │ └── user_handler.go │ │ └── grpc/ │ │ └── user_service.go │ ├── middleware/ # HTTP middleware │ │ ├── auth.go │ │ └── logging.go │ └── config/ # Configuration │ └── config.go ├── pkg/ # Public libraries │ ├── logger/ │ └── database/ ├── proto/ # gRPC definitions │ └── user.proto ├── Dockerfile ├── go.mod └── go.sum
HTTP API with Gin (Clean Architecture)
package main import ( "context" "net/http" "os" "os/signal" "syscall" "time" "github.com/gin-gonic/gin" "go.uber.org/zap" ) // Domain Entity type User struct { ID string `json:"id"` Email string `json:"email"` Name string `json:"name"` CreatedAt time.Time `json:"created_at"` } // Repository Interface type UserRepository interface { Create(ctx context.Context, user *User) error FindByID(ctx context.Context, id string) (*User, error) FindByEmail(ctx context.Context, email string) (*User, error) } // Use Case type UserUseCase struct { repo UserRepository logger *zap.Logger } func NewUserUseCase(repo UserRepository, logger *zap.Logger) *UserUseCase { return &UserUseCase{repo: repo, logger: logger} } func (uc *UserUseCase) CreateUser(ctx context.Context, email, name string) (*User, error) { // Check if user exists existing, err := uc.repo.FindByEmail(ctx, email) if err != nil && err != ErrNotFound { uc.logger.Error("failed to check existing user", zap.Error(err)) return nil, err } if existing != nil { return nil, ErrUserAlreadyExists } // Create new user user := &User{ ID: generateID(), Email: email, Name: name, CreatedAt: time.Now(), } if err := uc.repo.Create(ctx, user); err != nil { uc.logger.Error("failed to create user", zap.Error(err)) return nil, err } uc.logger.Info("user created", zap.String("user_id", user.ID)) return user, nil } // HTTP Handler type UserHandler struct { useCase *UserUseCase logger *zap.Logger } func NewUserHandler(useCase *UserUseCase, logger *zap.Logger) *UserHandler { return &UserHandler{useCase: useCase, logger: logger} } type CreateUserRequest struct { Email string `json:"email" binding:"required,email"` Name string `json:"name" binding:"required,min=2"` } func (h *UserHandler) CreateUser(c *gin.Context) { var req CreateUserRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } user, err := h.useCase.CreateUser(c.Request.Context(), req.Email, req.Name) if err != nil { if err == ErrUserAlreadyExists { c.JSON(http.StatusConflict, gin.H{"error": "user already exists"}) return } h.logger.Error("failed to create user", zap.Error(err)) c.JSON(http.StatusInternalServerError, gin.H{"error": "internal server error"}) return } c.JSON(http.StatusCreated, user) } // Main Application func main() { logger, _ := zap.NewProduction() defer logger.Sync() // Initialize dependencies db := initDatabase() repo := NewPostgresUserRepository(db) useCase := NewUserUseCase(repo, logger) handler := NewUserHandler(useCase, logger) // Setup router router := gin.Default() router.Use(LoggingMiddleware(logger)) router.Use(RequestIDMiddleware()) v1 := router.Group("/api/v1") { users := v1.Group("/users") { users.POST("", handler.CreateUser) users.GET("/:id", handler.GetUser) } } // Graceful shutdown srv := &http.Server{ Addr: ":8080", Handler: router, } go func() { if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { logger.Fatal("failed to start server", zap.Error(err)) } }() // Wait for interrupt signal quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit logger.Info("shutting down server...") ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := srv.Shutdown(ctx); err != nil { logger.Fatal("server forced to shutdown", zap.Error(err)) } logger.Info("server exited") }
gRPC Service
// proto/user.proto syntax = "proto3"; package user; option go_package = "github.com/yourorg/user-service/proto"; service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc GetUser(GetUserRequest) returns (GetUserResponse); } message CreateUserRequest { string email = 1; string name = 2; } message CreateUserResponse { string id = 1; string email = 2; string name = 3; } // Implementation package grpc import ( "context" pb "github.com/yourorg/user-service/proto" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) type UserServiceServer struct { pb.UnimplementedUserServiceServer useCase *UserUseCase logger *zap.Logger } func (s *UserServiceServer) CreateUser(ctx context.Context, req *pb.CreateUserRequest) (*pb.CreateUserResponse, error) { user, err := s.useCase.CreateUser(ctx, req.Email, req.Name) if err != nil { if err == ErrUserAlreadyExists { return nil, status.Error(codes.AlreadyExists, "user already exists") } s.logger.Error("failed to create user", zap.Error(err)) return nil, status.Error(codes.Internal, "internal error") } return &pb.CreateUserResponse{ Id: user.ID, Email: user.Email, Name: user.Name, }, nil }
Worker Pool Pattern
package worker import ( "context" "sync" ) type Job struct { ID string Data interface{} } type Result struct { JobID string Data interface{} Error error } type WorkerPool struct { workerCount int jobs chan Job results chan Result wg sync.WaitGroup } func NewWorkerPool(workerCount int) *WorkerPool { return &WorkerPool{ workerCount: workerCount, jobs: make(chan Job, workerCount*2), results: make(chan Result, workerCount*2), } } func (wp *WorkerPool) Start(ctx context.Context, processor func(Job) (interface{}, error)) { for i := 0; i < wp.workerCount; i++ { wp.wg.Add(1) go wp.worker(ctx, processor) } } func (wp *WorkerPool) worker(ctx context.Context, processor func(Job) (interface{}, error)) { defer wp.wg.Done() for { select { case job, ok := <-wp.jobs: if !ok { return } data, err := processor(job) wp.results <- Result{ JobID: job.ID, Data: data, Error: err, } case <-ctx.Done(): return } } } func (wp *WorkerPool) Submit(job Job) { wp.jobs <- job } func (wp *WorkerPool) Results() <-chan Result { return wp.results } func (wp *WorkerPool) Stop() { close(wp.jobs) wp.wg.Wait() close(wp.results) }
Resource Files
resources/clean-architecture.md
- Layered architecture implementation
- Dependency injection patterns
- Interface design
- Testability strategies
resources/grpc-services.md
- Proto definition best practices
- Interceptors and middleware
- Error handling
- Streaming patterns
resources/concurrency-patterns.md
- Goroutines and channels
- Worker pools
- Context usage
- Race condition prevention
resources/database-integration.md
- GORM patterns
- Connection pooling
- Transaction management
- Migration strategies
resources/testing-strategies.md
- Unit testing with mocks
- Integration testing
- Table-driven tests
- Benchmarking
resources/middleware-auth.md
- Authentication middleware
- JWT validation
- Rate limiting
- CORS configuration
resources/observability.md
- Structured logging (zap)
- Prometheus metrics
- Distributed tracing
- Health checks
resources/docker-kubernetes.md
- Multi-stage Dockerfiles
- Kubernetes manifests
- Helm charts
- Health probes
Best Practices
- Use context for cancellation and timeouts
- Handle errors explicitly, don't ignore
- Use interfaces for dependency injection
- Leverage Go's concurrency primitives
- Write table-driven tests
- Use structured logging
- Implement health and readiness endpoints
- Use migrations for database schema
- Version your APIs
- Document with godoc comments
- Use linters (golangci-lint)
- Follow effective Go guidelines
Tools & Libraries
- Web Frameworks: Gin, Echo, Fiber
- gRPC: google.golang.org/grpc
- Database: GORM, sqlx
- Logging: zap, logrus
- Config: viper
- Testing: testify, gomock
- Metrics: prometheus/client_golang
- Tracing: OpenTelemetry
Common Patterns
Error Wrapping
import "github.com/pkg/errors" func (r *Repository) GetUser(id string) (*User, error) { user, err := r.db.FindByID(id) if err != nil { return nil, errors.Wrap(err, "failed to get user from database") } return user, nil }
Context Timeout
func (uc *UseCase) Process(ctx context.Context) error { ctx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() return uc.repo.SlowOperation(ctx) }
Status: Production-Ready Last Updated: 2025-11-04 Performance: Optimized for high-throughput, low-latency microservices