Claude Skills Guide

Claude Code Skills for Golang Microservices

Building Golang microservices requires handling repetitive patterns, from setting up HTTP handlers to configuring Dockerfiles. Claude Code accelerates these workflows through built-in skills that understand Go’s idioms and microservice architecture patterns.

Available Skills for Go Development

Claude Code provides several skills that work well with Golang projects:

For Golang-specific work, you often describe your intent directly since no built-in /golang skill exists. The combination of these skills covers most microservice development needs.

Setting Up a Go Microservice Project

When starting a new Go microservice, structure your project for scalability. Create a project layout that separates handlers, services, and data access layers:

mkdir -p cmd/api internal/handler internal/service internal/repository pkg/config
cd cmd/api && go mod init github.com/yourorg/microservice

Initialize Go modules and add dependencies:

go get github.com/gin-gonic/gin github.com/jackc/pgx/v5 github.com/redis/go-redis/v9

This baseline structure supports the handler-service-repository pattern common in Go microservices.

Creating HTTP Handlers with Claude Code

When you need to create a new HTTP handler, describe the endpoint structure to Claude Code. For example:

Create a user handler with CreateUser, GetUser, and ListUsers methods using the repository pattern. Include request validation and error responses.

Claude Code generates handler code following Go conventions:

// internal/handler/user.go
package handler

import (
    "net/http"
    "strconv"

    "github.com/gin-gonic/gin"
    "github.com/yourorg/microservice/internal/service"
)

type UserHandler struct {
    service *service.UserService
}

func NewUserHandler(svc *service.UserService) *UserHandler {
    return &UserHandler{service: svc}
}

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.service.CreateUser(c.Request.Context(), req.ToModel())
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to create user"})
        return
    }

    c.JSON(http.StatusCreated, user)
}

func (h *UserHandler) GetUser(c *gin.Context) {
    id, err := strconv.ParseUint(c.Param("id"), 10, 64)
    if err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": "invalid user id"})
        return
    }

    user, err := h.service.GetUser(c.Request.Context(), id)
    if err != nil {
        c.JSON(http.StatusNotFound, gin.H{"error": "user not found"})
        return
    }

    c.JSON(http.StatusOK, user)
}

The generated code follows standard Go patterns: context propagation, error handling, and clean separation between layers.

Writing Unit Tests with /tdd Skill

The /tdd skill helps generate comprehensive tests for your Go code. Activate it and describe your test requirements:

/tdd Generate unit tests for the user service with mock repository. Test CreateUser validates input, GetUser returns correct data, and errors are handled properly.

The skill generates test files following Go testing conventions:

// internal/service/user_test.go
package service

import (
    "context"
    "errors"
    "testing"

    "github.com/stretchr/testify/assert"
    "github.com/stretchr/testify/mock"
)

type MockUserRepository struct {
    mock.Mock
}

func (m *MockUserRepository) Create(ctx context.Context, user *User) (*User, error) {
    args := m.Called(ctx, user)
    if args.Get(0) == nil {
        return nil, args.Error(1)
    }
    return args.Get(0).(*User), args.Error(1)
}

func (m *MockUserRepository) GetByID(ctx context.Context, id uint64) (*User, error) {
    args := m.Called(ctx, id)
    if args.Get(0) == nil {
        return nil, args.Error(1)
    }
    return args.Get(0).(*User), args.Error(1)
}

func TestUserService_CreateUser(t *testing.T) {
    mockRepo := new(MockUserRepository)
    svc := NewUserService(mockRepo)

    mockRepo.On("Create", mock.Anything, mock.AnythingOfType("*User")).
        Return(&User{ID: 1, Email: "test@example.com"}, nil)

    user, err := svc.CreateUser(context.Background(), &User{
        Email: "test@example.com",
        Name:  "Test User",
    })

    assert.NoError(t, err)
    assert.Equal(t, uint64(1), user.ID)
    mockRepo.AssertExpectations(t)
}

func TestUserService_CreateUser_ValidationError(t *testing.T) {
    mockRepo := new(MockUserRepository)
    svc := NewUserService(mockRepo)

    _, err := svc.CreateUser(context.Background(), &User{
        Email: "",
        Name:  "Test User",
    })

    assert.Error(t, err)
    assert.Contains(t, err.Error(), "email is required")
}

Run tests with the standard Go test command:

go test ./internal/service/... -v -cover

Docker Container Setup for Go Microservices

For Docker configuration, describe your requirements directly to Claude Code and it will generate optimized configurations:

Create a multi-stage Dockerfile for a Go API service. Use alpine base, build with CGO disabled, run as non-root user.

Claude produces optimized configurations:

# Build stage
FROM golang:1.21-alpine AS builder

WORKDIR /app

# Install dependencies
COPY go.mod go.sum ./
RUN go mod download

# Build application
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /api ./cmd/api

# Runtime stage
FROM alpine:3.19

RUN addgroup -g 1000 appgroup && \
    adduser -u 1000 -G appgroup -s /bin/sh -D appuser

WORKDIR /app

COPY --from=builder /api .

USER appuser

EXPOSE 8080

CMD ["./api"]

Build and run the container:

docker build -t my-go-service .
docker run -p 8080:8080 my-go-service

API Testing with /webapp Testing Skill

Test your microservice endpoints using the /webapp-testing skill. This skill understands how to validate API responses:

/webapp-testing Create a test suite for the user API endpoints. Test user creation returns 201, fetching a user returns 200, invalid input returns 400, and missing user returns 404.

The skill generates test code that can run against your running service:

// api_test.go
package main

import (
    "net/http"
    "net/http/httptest"
    "strings"
    "testing"

    "github.com/stretchr/testify/assert"
)

func TestCreateUserAPI(t *testing.T) {
    router := setupRouter()

    payload := `{"email":"test@example.com","name":"Test User"}`
    req, _ := http.NewRequest("POST", "/api/v1/users", 
        strings.NewReader(payload))
    req.Header.Set("Content-Type", "application/json")

    w := httptest.NewRecorder()
    router.ServeHTTP(w, req)

    assert.Equal(t, http.StatusCreated, w.Code)
    assert.Contains(t, w.Body.String(), "test@example.com")
}

func TestGetUserNotFound(t *testing.T) {
    router := setupRouter()

    req, _ := http.NewRequest("GET", "/api/v1/users/99999", nil)
    w := httptest.NewRecorder()
    router.ServeHTTP(w, req)

    assert.Equal(t, http.StatusNotFound, w.Code)
}

Run these tests against your running container or locally:

go test -v ./... -run TestCreateUserAPI

Database Integration

Claude Code can set up database connections and write efficient queries using GORM or SQLx. Here is a GORM repository pattern:

package repositories

import (
    "context"
    "user-service/internal/models"

    "gorm.io/gorm"
)

type UserRepository struct {
    db *gorm.DB
}

func NewUserRepository(db *gorm.DB) *UserRepository {
    return &UserRepository{db: db}
}

func (r *UserRepository) FindByID(ctx context.Context, id string) (*models.User, error) {
    var user models.User
    result := r.db.WithContext(ctx).First(&user, "id = ?", id)
    if result.Error != nil {
        return nil, result.Error
    }
    return &user, nil
}

Inter-Service Communication with gRPC

Go microservices often communicate via gRPC. Claude Code can set up protobuf schemas and generate the server implementation:

syntax = "proto3";

package user;

option go_package = "github.com/yourorg/user-service/pb";

service UserService {
    rpc GetUser (GetUserRequest) returns (User);
    rpc CreateUser (CreateUserRequest) returns (User);
}

message GetUserRequest {
    string id = 1;
}

message User {
    string id = 1;
    string email = 2;
    string name = 3;
}

Claude Code generates the Go code from your proto files and creates the gRPC server implementation. For broader inter-service communication patterns, see Claude Code Skills Microservices Communication Patterns.

Docker Compose for Local Development

Claude Code generates Docker Compose configurations for running your microservices with their dependencies locally:

version: '3.8'

services:
  user-service:
    build: .
    ports:
      - "8080:8080"
    environment:
      - DATABASE_URL=postgres://user:pass@db:5432/users
    depends_on:
      - db
      - redis

  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
      POSTGRES_DB: users

  redis:
    image: redis:7-alpine

Service Layer Patterns

Go microservices benefit from clear service layer separation. Claude Code helps generate service implementations that handle business logic.

// internal/service/user.go
package service

import (
    "context"
    "errors"

    "github.com/yourorg/microservice/internal/repository"
)

var (
    ErrUserNotFound   = errors.New("user not found")
    ErrEmailExists    = errors.New("email already exists")
    ErrInvalidInput   = errors.New("invalid input")
)

type UserService struct {
    repo *repository.UserRepository
}

func NewUserService(repo *repository.UserRepository) *UserService {
    return &UserService{repo: repo}
}

func (s *UserService) CreateUser(ctx context.Context, user *User) (*User, error) {
    if user.Email == "" {
        return nil, ErrInvalidInput
    }

    existing, _ := s.repo.GetByEmail(ctx, user.Email)
    if existing != nil {
        return nil, ErrEmailExists
    }

    return s.repo.Create(ctx, user)
}

func (s *UserService) GetUser(ctx context.Context, id uint64) (*User, error) {
    user, err := s.repo.GetByID(ctx, id)
    if err != nil {
        return nil, ErrUserNotFound
    }
    return user, nil
}

This pattern ensures your microservice handles errors consistently and validates data at the service layer.

Actionable Advice for Claude Code Workflow

  1. Start with clear prompts: Be specific about requirements. Instead of “Create a handler,” say “Create a REST handler for a user service with GET and POST endpoints using the Gin framework.”

  2. Iterative development: Generate code in small chunks. Create models first, then handlers, then services. This ensures each piece works before integrating.

  3. Use code reviews: Have Claude Code review generated code. It can identify potential issues like missing error handling or inefficient database queries.

  4. Leverage Claude Code for boilerplate: Save time on repetitive code like CRUD operations, middleware, and configuration loading.

  5. Test-driven approach: Ask Claude Code to generate tests alongside your implementation using the /tdd skill. This ensures your code is testable from the start.

Summary

Claude Code skills enhance Golang microservices development by automating handler generation, test creation, Docker configuration, and API testing. The /tdd and /webapp-testing skills, combined with direct prompting for Docker configuration, cover the full development lifecycle. For Go-specific patterns, describing your requirements directly to Claude Code produces idiomatic code that follows established conventions. Explore more backend patterns in the use cases hub.

Built by theluckystrike — More at zovo.one