Agent Skills: Go Development (1.25+)

Idiomatic Go 1.25+ development. Use when writing Go code, designing APIs, discussing Go patterns, or reviewing Go implementations. Emphasizes stdlib, concrete types, simple error handling, and minimal dependencies.

UncategorizedID: alexei-led/claude-code-config/writing-go

Install this agent skill to your local

pnpm dlx add-skill https://github.com/alexei-led/claude-code-config/tree/HEAD/src/skills/writing-go

Skill Files

Browse the full folder contents for writing-go.

Download Skill

Loading file tree…

src/skills/writing-go/SKILL.md

Skill Metadata

Name
writing-go

Go Development (1.25+)

Critical Output Rules

  • State stdlib-first choices explicitly: use net/http, encoding/json, context, and testing where practical before adding dependencies.
  • Avoid unnecessary dependencies. Add a library only when concrete requirements beat stdlib simplicity.
  • Prefer concrete types and small consumer-side interfaces only at real seams; do not abstract everything by default.
  • Error handling guidance must say normal failures return error, not panic; wrap with context using %w; avoid custom error hierarchies unless callers need distinct behavior.
  • Always mention behavior tests for success and error paths, even when only giving design or error-handling advice. Prefer table-driven tests with t.Run; stdlib testing is enough unless the project already uses another test library.
  • For handlers/services, pass context.Context through API boundaries and map service errors to HTTP status at the edge.
  • Do not run destructive shell commands. For broad or risky changes, state the risk and ask before acting.

Core Philosophy

Stdlib-first stance, concrete-types-over-any, consumer-side interfaces, flat control flow, explicit error handling, the no-destructive-commands safety rule, and the post-generation verification loop are in references/principles.md — read it before generating code.

Quick Patterns

Private Interface at Consumer

// service/user.go - private interface where it's USED
type userStore interface {
    Get(ctx context.Context, id string) (*User, error)
}

type Service struct {
    store userStore  // accepts interface
}

// repo/postgres.go - returns concrete type
func NewPostgresStore(db *sql.DB) *PostgresStore {
    return &PostgresStore{db: db}
}

Flat Control Flow (No Nesting)

// GOOD: guard clauses, early returns
func process(user *User) error {
    if user == nil {
        return ErrNilUser
    }
    if user.Email == "" {
        return ErrMissingEmail
    }
    if !isValidEmail(user.Email) {
        return ErrInvalidEmail
    }
    return doWork(user)
}

// BAD: nested conditions
func process(user *User) error {
    if user != nil {
        if user.Email != "" {
            if isValidEmail(user.Email) {
                return doWork(user)
            }
        }
    }
    return nil
}

Error Handling

if err := doThing(); err != nil {
    return fmt.Errorf("do thing: %w", err)  // always wrap
}

// Sentinel errors
if errors.Is(err, ErrNotFound) {
    return http.StatusNotFound
}

Concrete Types (Avoid any)

// GOOD: concrete types
func ProcessUsers(users []User) error { ... }
func GetUserByID(id string) (*User, error) { ... }

// BAD: unnecessary any
func ProcessItems(items []any) error { ... }
func GetByID(id any) (any, error) { ... }

Table-Driven Tests

tests := []struct {
    name    string
    input   string
    want    string
    wantErr bool
}{
    {"valid", "hello", "HELLO", false},
    {"empty", "", "", true},
}
for _, tt := range tests {
    t.Run(tt.name, func(t *testing.T) {
        got, err := Process(tt.input)
        if tt.wantErr {
            require.Error(t, err)
            return
        }
        require.NoError(t, err)
        assert.Equal(t, tt.want, got)
    })
}

Go 1.25 Features

  • testing/synctest: Deterministic concurrent testing
  • encoding/json/v2: 3-10x faster (GOEXPERIMENT=jsonv2)
  • runtime/trace.FlightRecorder: Production trace capture
  • Container-aware GOMAXPROCS: Auto-detects cgroup limits

References

  • principles.md - Core philosophy, safety rule, and verification loop (read before generating code)
  • PATTERNS.md - Detailed code patterns
  • TESTING.md - Testing with testify/mockery
  • CLI.md - CLI application patterns

Tooling

go build ./...           # Build
go test -race ./...      # Test with race detector
golangci-lint run        # Lint
mockery --all            # Generate mocks

Failure Cases

  • No Go files in repo / ambiguous project root: run find . -name 'go.mod' to locate modules before generating code; do not assume a single root.
  • Compilation or test failure after generation: quote the failing line, state the cause, show the exact fix. Do not retry blindly—diagnose first.