Claude Code for Go (Golang) — Complete Setup Guide

Claude Code works well with Go projects when configured to understand your module structure, error conventions, and test patterns. This guide covers the CLAUDE.md template, automated go test hooks, idiomatic Go configuration, and workflow patterns for HTTP services, CLI tools, and microservices.

Go CLAUDE.md Template

# Project: [Your Service Name]

## Stack
- Go 1.22
- Module: github.com/yourorg/yourservice (from go.mod)
- HTTP: net/http + chi router (or gin, echo, stdlib — specify yours)
- Database: pgx/v5 + sqlc (or database/sql, gorm — specify)
- Testing: go test, testify/assert, gomock

## Commands
```bash
go build ./...                  # build check
go test ./...                   # run all tests
go test ./... -race              # race detector
go test ./internal/... -v       # verbose test output
go test -run TestUserService     # single test
golangci-lint run               # lint
go vet ./...                    # vet
```

## Conventions
- Error wrapping: fmt.Errorf("functionName: %w", err)
- Context is always the first parameter for I/O functions
- Interfaces defined at call site, not definition package
- Table-driven tests using []struct{name, input, want, wantErr}
- No global state; pass dependencies via constructor or function params
- Avoid init() functions

## Project structure
- cmd/[service]/main.go — entry point
- internal/           — private packages
  - handler/          — HTTP handlers
  - service/          — business logic
  - store/            — database layer
  - model/            — shared types
- pkg/                — public/shared packages

Automated go test Hooks

Run tests after every edit so Claude sees failures immediately and fixes them in the same turn:

// .claude/settings.json
{
  "allowedTools": ["Edit", "Write", "Bash", "Read", "Glob", "Grep"],
  "hooks": [
    {
      "event": "PostToolUse",
      "matcher": "Edit|Write",
      "hooks": [{
        "type": "command",
        "command": "cd $PROJECT_ROOT && go test ./... -count=1 2>&1 | tail -25"
      }]
    }
  ]
}
Use -count=1 to disable Go's test result cache. Without it, Claude may see a cached pass and miss a newly introduced regression.

Race detector hook (for concurrent code)

{
  "event": "PostToolUse",
  "matcher": "Edit|Write",
  "hooks": [{
    "type": "command",
    "command": "cd $PROJECT_ROOT && go test ./... -race -count=1 2>&1 | tail -30"
  }]
}

Lint hook (golangci-lint)

{
  "event": "PostToolUse",
  "matcher": "Write",
  "hooks": [{
    "type": "command",
    "command": "cd $PROJECT_ROOT && golangci-lint run --fast 2>&1 | head -20"
  }]
}

Teaching Claude Idiomatic Go

By default Claude writes correct Go but may default to verbose patterns. Add these to CLAUDE.md:

PatternCLAUDE.md instruction
Error wrapping"Wrap errors: fmt.Errorf("methodName: %w", err)"
Context propagation"ctx is always the first param for any function with I/O"
Interfaces"Define interfaces at call site, in the consumer package"
Constructors"Use NewFoo(deps...) *Foo pattern, no init()"
Table tests"Use table-driven tests: tests := []struct{name, input, want}{}"
Goroutine safety"Use errgroup for concurrent tasks; always propagate context cancellation"

HTTP Service Workflows

Add a new endpoint

claude "add a PATCH /users/{id}/status endpoint.
Handler in internal/handler/user.go.
Service method in internal/service/user.go.
Store query in internal/store/user.go using sqlc.
Write table-driven tests for each layer.
Run go test ./... to verify."

Add middleware

claude "add rate-limiting middleware using golang.org/x/time/rate.
Limit: 100 req/min per IP. Return 429 with Retry-After header.
Wire it into cmd/api/main.go before the router.
Add integration test using httptest."

Database migration + model

claude "add a 'tags' column (text[], nullable) to the posts table.
Create a Goose migration file in migrations/.
Update the sqlc query file for posts.
Regenerate sqlc (sqlc generate).
Update the Post model and any handlers that return posts."

Concurrency Patterns

Concurrent fetch with errgroup

claude "rewrite FetchUserDashboard to fetch user, posts, and followers
concurrently using errgroup. Cancel all goroutines if any fails.
Propagate ctx. The function signature should stay the same."

Worker pool

claude "implement a worker pool for processing email jobs.
Pool size configurable via constructor. Use a buffered channel for the queue.
Graceful shutdown: drain queue on context cancel. Add tests with race detector."

CLI Tool Workflows (cobra/urfave)

# CLAUDE.md additions for CLI tools

## CLI Framework
- cobra v1.8 (cmd/ directory structure)
- Each subcommand in cmd/[subcommand].go
- Config via viper (config.yaml or env vars)
- Output: text to stdout, errors to stderr

## Commands
go run . [subcommand] [flags]   # test locally
go build -o ./bin/[name] .      # build binary
claude "add a 'sync' subcommand to the CLI. Usage: tool sync --source=dir --dest=bucket.
Use cobra for flag parsing. Progress bar with github.com/schollz/progressbar.
Dry-run flag --dry-run that prints what would be uploaded without uploading.
Write a unit test for the file collection logic."

5 Tips for Go + Claude Code

  1. Add your .golangci.yml to the repo and reference it in CLAUDE.md. Claude will generate code that passes your specific linter configuration.
  2. For generated code (sqlc, protobuf, mocks), tell Claude: "Never edit files in internal/store/generated/ — those are sqlc output." Claude will correctly regenerate via the tool command instead of editing directly.
  3. Use go test -run TestXxx -v in your hook for focused TDD. Switch to go test ./... for final verification.
  4. Tell Claude your Go version. Go 1.22 has range-over-integer, range-over-func, and enhanced http.ServeMux. Claude will use the right idioms for your version.
  5. For gRPC services, share your .proto files with Claude and tell it "generate handlers that match the proto service definition exactly". Claude reads protos fluently.
📘 Free: 5 sample Claude Code prompts · plus the £3 pack with 25 moreSee the free 5 →