Agent skill

Go Idioms

by irahardianto in irahardianto/awesome-agv

Go idioms and patterns: stdlib conventions, explicit error wrapping (%w), small interfaces, goroutines/channels concurrency, table-driven tests, and gofumpt formatting.

MITAuto-check passedDevelopment

Install Go Idioms

skills CLI
$ npx skills add irahardianto/awesome-agv --skill go-idioms -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install irahardianto/awesome-agv go-idioms --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/irahardianto/awesome-agv.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/go-idioms .claude/skills/go-idioms && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
go-idioms
GitHub stars
156
Token cost
~6.3k tokens
SKILL.md length
2,149 words
Files
4 (incl. references)
Skills in repo
34
Repo updated
First seen
Licence
MIT

At a glance

Go idioms and patterns: stdlib conventions, explicit error wrapping (%w), small interfaces, goroutines/channels concurrency, table-driven tests, and gofumpt formatting.

  • Works in 12 steps: Core Philosophy → When to Load References → Toolchain and Go Version → …
  • Reviewing Go services and packages
  • Calls go
  • Tasks that involve Async programming

What it does

Go Idioms is an agent skill from irahardianto/awesome-agv. Go idioms and patterns: stdlib conventions, explicit error wrapping (%w), small interfaces, goroutines/channels concurrency, table-driven tests, and gofumpt formatting. Use when writing, refactoring, or reviewing Go services and packages.

Its SKILL.md is about 6.3k tokens, which your agent loads only when the skill is triggered. The skill folder holds 4 other files, including reference files (for example `references/go-patterns-and-anti-patterns.md`, `references/project-structure.md` and `references/recommended-dependencies.md`).

It sits in Development, covering Async programming and Refactoring. It works with Go. The repository describes itself as: Comprehensive sets of standards and practices designed to elevate the capabilities of AI coding agents. The licence is MIT.

When your agent uses it

  • Reviewing Go services and packages
  • Tasks that involve Async programming
  • Tasks that involve Refactoring

Example prompts

  • “/go-idioms”

Workflow steps

12 steps, taken from the step headings in SKILL.md.

  1. Core Philosophy
  2. When to Load References
  3. Toolchain and Go Version
  4. Error Handling
  5. Interfaces
  6. Goroutines and Channels
  7. Naming Conventions
  8. Idiomatic Patterns
  9. Testing
  10. Formatting and Static Analysis
  11. Documentation
  12. Dependency Management

What it can do on your machine

Read from SKILL.md and the folder at commit 9e997ba. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • go

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Go Idioms loads about 6.3k tokens when it runs, and up to ~15k if it reads all its reference files. Until then it costs about 62 tokens; SKILL.md has 2,149 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~62
When it runs · the whole SKILL.md, loaded when a task matches
~6.3k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~15k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from irahardianto/awesome-agv at commit 9e997ba, republished under its MIT licence (© irahardianto). 2,149 words, ~6,251 tokens.

Download SKILL.mdSave it as .claude/skills/go-idioms/SKILL.md (or your agent's skills folder). This skill also uses 3 other files; get the full folder from GitHub.
name
go-idioms
description
Go idioms and patterns: stdlib conventions, explicit error wrapping (%w), small interfaces, goroutines/channels concurrency, table-driven tests, and gofumpt formatting. Use when writing, refactoring, or reviewing Go services and packages.

Go Idioms and Patterns

1. Core Philosophy

Go favors simplicity, explicitness, and readability. The language is intentionally small — resist the urge to import patterns from other languages. If it looks boring and obvious, it's probably idiomatic Go.

Scope: This file covers Go-specific coding idioms. For file layout, see references/project-structure.md. For detailed safety, SAST, and performance patterns, see references/go-patterns-and-anti-patterns.md. For logging library choice, see the logging-implementation skill. For quality commands, see the code-idioms-and-conventions rule.

Loading Guards: If the project has no go.mod, this skill does not apply.


2. When to Load References
SituationReference to Load
Starting a new project or setting up file layoutreferences/project-structure.md
Choosing packages, go.mod setup, or golangci-lint configreferences/recommended-dependencies.md
Writing code that handles I/O, concurrency, or user inputreferences/go-patterns-and-anti-patterns.md

3. Toolchain and Go Version

Default to the latest stable Go release. As of August 2026, Go 1.24 is the baseline with the Go module system.

Key version milestones:

  • 1.24+ — go tool for tool dependencies, swiss table map implementation
  • 1.23+ — range-over-func (iterator protocol), unique package
  • 1.22+ — range-over-integer, loop variable per-iteration scoping (eliminates loop variable capture bugs), enhanced ServeMux with method-based routing
  • 1.21+ — log/slog structured logging, maps and slices stdlib packages, sync.OnceFunc / sync.OnceValue / sync.OnceValues, min / max builtins, clear builtin
  • 1.18+ — Generics, fuzz testing with testing.F

Example go.mod configuration:

go
module github.com/user/project

go 1.24.0

toolchain go1.24.0

4. Error Handling
  1. Always return errors — never panic in library or business code

    • panic is reserved for truly unrecoverable states (programmer errors, nil dereference)
    • Use recover only at top-level goroutine boundaries (middleware, server startup)
  2. Wrap errors with context using %w

    • Don't re-wrap at every level. Wrap once with meaningful context where it matters.

    ✅ Preserves the error chain for errors.Is / errors.As

    go
    return fmt.Errorf("creating task for user %s: %w", userID, err)

    ❌ Loses the error chain

    go
    return fmt.Errorf("creating task: %v", err)
  3. Error string formatting

    • Error strings should be lowercase and have no trailing punctuation.
    • Go convention from Code Review Comments.

    ✅ Correct formatting

    go
    return fmt.Errorf("failed to open file %q: %w", path, err)

    ❌ Incorrect formatting

    go
    return fmt.Errorf("Failed to open file: %w.", err)
  4. Use errors.Join for multi-error aggregation (Go 1.20+)

    go
    var errs []error
    if err := doFirst(); err != nil {
        errs = append(errs, err)
    }
    if err := doSecond(); err != nil {
        errs = append(errs, err)
    }
    return errors.Join(errs...)
  5. Use sentinel errors for expected branch conditions

    go
    // Define in errors.go
    var ErrNotFound = errors.New("not found")
    var ErrUnauthorized = errors.New("unauthorized")
    
    // Caller checks with errors.Is
    if errors.Is(err, ErrNotFound) {
        // handle
    }
  6. Use typed errors for rich domain errors

    go
    type ValidationError struct {
        Field   string
        Message string
    }
    func (e *ValidationError) Error() string {
        return fmt.Sprintf("validation failed on %s: %s", e.Field, e.Message)
    }
    
    // Caller unwraps with errors.As
    var ve *ValidationError
    if errors.As(err, &ve) {
        // access ve.Field, ve.Message
    }
  7. Handle errors at the right level

    • Propagate upward until you have enough context to act on them; don't swallow or re-wrap the same error twice.
  8. Use lazy evaluation for fallback values

    • Prefer creating errors lazily only when a failure occurs to avoid unnecessary allocations.

5. Interfaces
  1. Keep interfaces small — one or two methods is ideal

    ✅ Focused, composable

    go
    type Reader interface { Read(p []byte) (n int, err error) }
    type Writer interface { Write(p []byte) (n int, err error) }

    ❌ Monolithic

    go
    type FileManager interface {
        Read()
        Write()
        Delete()
        List()
        Stat()
    }
  2. "Accept interfaces, return structs"

    • Function parameters: accept interfaces for flexibility and testability
    • Return values: return concrete structs so callers can access all methods
  3. Define interfaces where they are used, not where they are implemented

    ✅ Defined in the consumer package (task feature)

    go
    // task/storage.go
    type Storage interface {
        GetByID(ctx context.Context, id string) (*Task, error)
    }
    
    // postgres.go implements Storage — it does NOT define it
  4. Implicit satisfaction is a feature — don't use embedding to "implement" interfaces

    • Any type with the right method set satisfies an interface automatically
    • No implements keyword needed or wanted
  5. any vs interface{}

    • Always use any (Go 1.18+ alias) instead of interface{}.
  6. Interface compliance verification

    • Use var _ Interface = (*Struct)(nil) to guarantee a type implements an interface at compile time.
    go
    var _ Storage = (*PostgresStorage)(nil)
  7. When NOT to use interfaces

    • Premature abstraction violates YAGNI. Do not create an interface until you have 3+ implementations (or you need to mock it for testing in test-driven design).
  8. Generic interfaces with type parameters (Go 1.18+)

    go
    type Repository[T any] interface {
        FindByID(ctx context.Context, id string) (T, error)
    }

6. Goroutines and Channels

For general concurrency principles (race conditions, deadlocks, message passing), see concurrency-and-threading-principles.md. This section covers Go-specific mechanics.

  1. Always pass context.Context as the first parameter

    ✅ Pass context

    go
    func (s *Service) GetTask(ctx context.Context, id string) (*Task, error)

    ❌ No way to cancel or propagate deadlines

    go
    func (s *Service) GetTask(id string) (*Task, error)
  2. Never start a goroutine without knowing how it will stop (Anti-pattern: Goroutine Leak)

    • Every goroutine must have a definitive exit path (e.g., via context.Context cancellation or channel close).

    ✅ Goroutine is bounded by context cancellation

    go
    go func() {
        for {
            select {
            case <-ctx.Done():
                return
            case item := <-ch:
                process(item)
            }
        }
    }()
  3. Goroutine lifecycle management with sync.WaitGroup

    go
    var wg sync.WaitGroup
    for _, task := range tasks {
        wg.Add(1)
        go func(t Task) {
            defer wg.Done()
            process(t)
        }(task)
    }
    wg.Wait()
  4. Use errgroup for concurrent fan-out with error collection

    go
    g, ctx := errgroup.WithContext(ctx)
    g.Go(func() error { return fetchUsers(ctx) })
    g.Go(func() error { return fetchOrders(ctx) })
    if err := g.Wait(); err != nil { ... }
  5. Prefer channels for ownership transfer; mutexes for shared state

    • Channel: "I'm handing this data to you"
    • Mutex: "We're both reading/writing this shared thing"
  6. Close channels from the sender, never the receiver

  7. context.AfterFunc (Go 1.21+)

    • Trigger an action asynchronously when a context completes.
    go
    stop := context.AfterFunc(ctx, func() {
        cleanupResources()
    })
    defer stop()
  8. Channel direction restrictions in function signatures

    • Narrow channel directions for compile-time safety.
    go
    func producer(ch chan<- int) {} // Send-only
    func consumer(ch <-chan int) {} // Receive-only
  9. sync.OnceFunc / sync.OnceValue (Go 1.21+)

    • Use for lazy, thread-safe initialization.
    go
    var initDb = sync.OnceValue(func() *sql.DB {
        // initialize DB
        return db
    })
  10. select with default for non-blocking operations

    go
    select {
    case ch <- data:
        // Sent
    default:
        // Channel is full or unbuffered with no receiver, move on
    }
  11. context.WithoutCancel (Go 1.21+)

    • Create a derived context that is not cancelled when the parent is. Use for background operations that must outlive the request (e.g., async audit logging, metrics flush).
    go
    // Request-scoped context cancelled when handler returns
    bgCtx := context.WithoutCancel(ctx)
    go func() {
        // This work continues even after the parent request completes
        auditLog(bgCtx, event)
    }()

    ⚠️ Use sparingly — most work should respect parent cancellation. Reserve for fire-and-forget operations where partial completion is acceptable.

  12. Structured concurrency with conc (when errgroup isn't enough)

    • errgroup covers fan-out with error collection. For additional needs — panic recovery within goroutines, bounded worker pools with panic safety — use github.com/sourcegraph/conc.
    go
    // conc.WaitGroup recovers panics and re-panics on Wait()
    wg := conc.NewWaitGroup()
    wg.Go(func() { process(item1) })
    wg.Go(func() { process(item2) })
    wg.Wait() // Re-panics if any goroutine panicked
    • Prefer errgroup for simple fan-out. Reach for conc when you need panic recovery or bounded concurrency with conc/pool.

7. Naming Conventions
  1. Receiver names: short, consistent, and the first letter of the type ✅

    go
    func (s *Service) Create(...) {}

    ❌

    go
    func (svc *Service) Create(...) {} // too verbose
    func (self *Service) Create(...) {} // not Go
  2. Package names: short, lowercase, no underscores, no plurals ✅ package task ❌ package tasks (plural) ❌ package task_service (underscore)

  3. Acronyms follow Go conventions (all caps or all lowercase) ✅ userID, HTTPClient ❌ userId, HttpClient

  4. Unexported identifiers omit the type name — if it's private, keep it terse

  5. Don't stutter — task.Task is fine; task.TaskService is not

  6. Error string formatting

    • Error strings should not be capitalized or end with punctuation.
  7. Getter naming

    • No Get prefix in Go. Use user.Name() not user.GetName().
  8. Test naming

    • Use the TestFunctionName_Scenario_Expected pattern.
    go
    func TestCalculateDiscount_NegativeInput_ReturnsError(t *testing.T) { ... }
  9. Constructor naming

    • Use New prefix (NewService, NewClient).
  10. Interface naming

    • Use the -er suffix for single-method interfaces (Reader, Writer, Stringer).

8. Idiomatic Patterns
  1. Range-over-func iterators (Go 1.23+)

    go
    // Definition
    func Count(n int) iter.Seq[int] {
        return func(yield func(int) bool) {
            for i := 0; i < n; i++ {
                if !yield(i) {
                    return
                }
            }
        }
    }
    
    // Usage
    for i := range Count(5) {
        fmt.Println(i)
    }
  2. Nil slice vs empty slice semantics

    • var s []int (nil slice) marshals to null in JSON.
    • s := []int{} or make([]int, 0) (empty slice) marshals to [] in JSON.
  3. Type assertions with comma-ok pattern

    go
    if str, ok := val.(string); ok {
        fmt.Println(str)
    }
  4. Type switches for polymorphic dispatch

    go
    switch v := val.(type) {
    case string:
        fmt.Println("String:", v)
    case int:
        fmt.Println("Int:", v)
    default:
        fmt.Println("Unknown type")
    }
  5. strings.Builder for string concatenation

    • Avoid + inside loops. Use strings.Builder.
    go
    var b strings.Builder
    b.WriteString("hello")
    b.WriteString("world")
    return b.String()
  6. slices and maps stdlib packages (Go 1.21+)

    • Use the built-in generic functions for sorting, reversing, filtering, and checking elements.
    go
    slices.Sort(mySlice)
    if slices.Contains(mySlice, target) { ... }
  7. Variadic append

    • Use append(s1, s2...) instead of loops.
  8. Pre-allocation

    • Use make([]T, 0, n) when the size is known to avoid reallocation overhead.
  9. sync.Pool for hot-path allocations

    • Use only for POINTER values to reduce GC pressure.
  10. time.NewTicker vs time.Tick

    • time.Tick leaks the underlying ticker. Always prefer time.NewTicker which can be stopped via ticker.Stop().
  11. Struct embedding for composition (not inheritance)

    • Use struct embedding to reuse fields and methods where it forms an "is-a" relationship, not for general code reuse.
  12. Early returns / guard clauses

    • Reduce nesting.
    go
    if err != nil {
        return err
    }
    // Continue happy path
  13. Keep function complexity low

    • Keep cyclomatic complexity under 10 (matching Rust/TS guidelines).
  14. Functional options for optional configuration

go
type Option func(*Service)

func WithTimeout(d time.Duration) Option {
    return func(s *Service) { s.timeout = d }
}

func NewService(store Storage, opts ...Option) *Service {
    s := &Service{store: store, timeout: 30 * time.Second}
    for _, o := range opts { o(s) }
    return s
}
  1. defer for cleanup — always use error-checked closures

Every deferred cleanup call that returns an error MUST check and log the error. Never use bare defer X.Close() — the discarded error hides resource leak failures.

❌ NEVER: Error silently discarded

go
defer rows.Close()

✅ ALWAYS: Error-checked closure with structured logging

go
rows, err := db.QueryContext(ctx, query)
if err != nil { return fmt.Errorf("querying tasks: %w", err) }
defer func() {
    if err := rows.Close(); err != nil {
        slog.Warn("failed to close rows", "error", err, "operation", "ListTasks")
    }
}()

Transaction rollback: ❌ NEVER

go
defer tx.Rollback()

✅ ALWAYS: Guard against sql.ErrTxDone (already committed)

go
defer func() {
    if err := tx.Rollback(); err != nil && !errors.Is(err, sql.ErrTxDone) {
        slog.Error("failed to rollback transaction", "error", err, "operation", "CreateOrder")
    }
}()

HTTP response body: ❌ NEVER

go
defer resp.Body.Close()

✅ ALWAYS: Drain then close (prevents connection reuse issues)

go
defer func() {
    if _, err := io.Copy(io.Discard, resp.Body); err != nil {
        slog.Warn("failed to drain response body", "error", err)
    }
    if err := resp.Body.Close(); err != nil {
        slog.Warn("failed to close response body", "error", err)
    }
}()
  1. Avoid init() functions

    • They run implicitly and make testing harder; prefer explicit initialization in main or constructors.
  2. Use named return values only for documentation or defer-based cleanup

    • Never rely on naked returns in non-trivial functions.
  3. unique.Handle for string interning (Go 1.23+)

    • Deduplicate frequently repeated values (user IDs, status strings) to reduce memory.
    go
    import "unique"
    
    h := unique.Make("active")
    // h.Value() returns "active"
    // Two handles with the same underlying value compare as equal
    h1 := unique.Make("active")
    fmt.Println(h == h1) // true — same canonical representation
    • Use when you have many copies of the same string in memory (e.g., status enums parsed from JSON). Don't use for unique values — the interning overhead is wasted.

Show full SKILL.md (939 more words)Show less
9. Testing

Test file naming and pyramid proportions are defined in testing-strategy.md. This section covers Go-specific tooling only.

  1. Table-driven tests are the default pattern

    go
    func TestCalculateDiscount(t *testing.T) {
        tests := []struct {
            name     string
            input    float64
            expected float64
            wantErr  bool
        }{
            {"zero items", 0, 0, false},
            {"negative input", -1, 0, true},
        }
        for _, tt := range tests {
            t.Run(tt.name, func(t *testing.T) {
                got, err := calculateDiscount(tt.input)
                if tt.wantErr {
                    require.Error(t, err)
                    return
                }
                require.NoError(t, err)
                assert.Equal(t, tt.expected, got)
            })
        }
    }
  2. Use testify for assertions

    • require for fatal assertions, assert for non-fatal.
  3. Run with the race detector in CI

    • go test -race ./...
  4. Use httptest.NewRecorder() for HTTP handler tests

    • No live server needed.
  5. Test behaviour, not implementation

    • Assert on outputs and side effects, not internal field values.
  6. Test helpers with t.Helper() and testing.TB interface

    go
    func createTestUser(t testing.TB) *User {
        t.Helper() // Corrects line numbers in failure output
        // ...
    }
  7. t.Cleanup() for resource teardown

    • Automatically cleans up resources without needing defers across multiple helper functions.
    go
    func setupDB(t *testing.T) *sql.DB {
        db := connect()
        t.Cleanup(func() { db.Close() })
        return db
    }
  8. Fuzz testing with testing.F (Go 1.18+)

    go
    func FuzzParse(f *testing.F) {
        f.Add("valid_input")
        f.Fuzz(func(t *testing.T, input string) {
            Parse(input) // ensure it never panics
        })
    }
  9. Benchmark patterns with testing.B

    go
    func BenchmarkProcess(b *testing.B) {
        b.ReportAllocs() // ALWAYS report allocations
        b.ResetTimer()   // Ignore setup time
        for i := 0; i < b.N; i++ {
            Process()
        }
    }
  10. Golden file testing

    • For large, complex outputs (like JSON or HTML), use golden files and compare against them.
  11. Test coverage non-negotiable policy

    • Every new exported function/method MUST have tests.
    • Every branch MUST be exercised.
  12. Coverage commands

    • Run go test -cover ./... and go test -coverprofile=coverage.out ./....
  13. Test Double Selection Table

ApproachWhen to Use
Hand-written fake (implement interface)Simple interface, few methods, need stateful behavior
gomock/mockgenComplex interface, need to verify call counts, argument matching
testify/mockComplex interface, prefer fluent assertion API
Table-driven testsSame logic, multiple input/output pairs
go-cmpDeep equality comparison with custom options

Prefer hand-written fakes for core domain traits.


10. Formatting and Static Analysis

All of the following must pass with zero warnings/errors before any commit. See code-idioms-and-conventions.md for the full checklist.

Feedback Loop — Development Workflow:

PhaseCommandPurpose
TDD / rapid iterationgo vet ./...Type-checks and correctness — fastest loop
Pre-commitgolangci-lint runAggregated linting — must pass zero warnings
Pre-commitgofumpt -l -w .Formatting — non-negotiable
Pre-commitgo test -race ./...Unit tests with race detector
Coverage verificationgo test -coverprofile=c.out ./...Verify before merging
Security auditgovulncheck ./...CVE scanning

Lint suppression policy — NEVER suppress these:

LintWhat It SignalsWhat To Do Instead
errcheckUnchecked error returnsHandle the error — use error-checked closure in defer
govet shadowVariable shadowingRename the inner variable
staticcheck SA*Correctness issuesFix the underlying bug
gosec G* (security)Security vulnerabilityFix the vulnerability
cyclop / gocognitFunction too complexDecompose into smaller functions

Acceptable suppressions (with mandatory // nolint: comment + rationale):

LintWhen Acceptable
gosec G104 (unhandled error)In test code only, with // nolint:gosec // test-only
revive exportedWhen the exported symbol is intentionally part of API design

Rule of thumb: If you're about to write //nolint:, stop and ask if you're suppressing a real design problem.

//nolint:errcheck is NEVER acceptable. If a function returns an error, handle it — even in defer. Use an error-checked closure. This is the #1 source of audit findings.

Logging: Never use fmt.Println or log.Printf in production service code — these produce unstructured output. Use log/slog (stdlib, Go 1.21+) or the project's chosen adapter. See @.agents/skills/logging-implementation/SKILL.md for the required library and patterns.


11. Documentation
  1. Godoc conventions

    • Package-level doc comment should exist for all exported packages.
    • All exported symbols (functions, structs, interfaces, vars, consts) MUST have a documentation comment starting with the name of the symbol.
  2. Example functions

    • Use func ExampleFunction() with // Output: comments at the end of the function body for runnable examples in Godoc.
    go
    func ExampleHello() {
        fmt.Println("Hello")
        // Output: Hello
    }
  3. Package doc

    • For complex packages, place package documentation in a dedicated doc.go file.
  4. Document the WHY, not the WHAT

    • The code shows what is happening. Comments explain why it is done this way (design rationale, edge cases, workarounds).

12. Dependency Management
  1. Minimize dependency count

    • Go stdlib is highly comprehensive. Rely on it heavily before bringing in external packages.
  2. Commit go.sum always

    • Both go.mod and go.sum belong in version control to guarantee reproducible builds.
  3. go mod tidy before commits

    • Always run this to prune unused dependencies and resolve checksums.
  4. govulncheck in CI

    • Continuously scan for vulnerabilities in your module dependency tree.
  5. Module proxy and checksum database

    • Use GOPROXY and the checksum database. For private modules, configure GOPRIVATE or GONOSUMCHECK.
  6. Prefer stdlib over third-party

    • When feature parity exists (e.g., log/slog vs zap), use the stdlib.

13. Configuration and Environment
  1. Never scatter os.Getenv() calls throughout codebase

    • It makes dependencies opaque and testing difficult.
  2. Centralized config struct parsed at startup

    • Parse all configurations into a central Config struct once, then inject it (or its subsets) where needed.
  3. Fail fast

    • Fail at boot for missing required configuration, not later at the first time of use.
  4. Example with struct tags and validation

    go
    type Config struct {
        Port     int    `env:"PORT" envDefault:"8080"`
        Database string `env:"DATABASE_URL" envRequired:"true"`
    }
    
    func LoadConfig() (*Config, error) {
        // load and validate
    }

14. Safety, Security, and Performance
  • Key safety rules (non-negotiable):
    • Never ignore errors.
    • Always close resources safely in a defer.
    • Validate all user input at the system boundary.
  • For a full catalog: Point to references/go-patterns-and-anti-patterns.md.
  • For Go-specific profiling: Point to the perf-optimization skill.

  • Code Idioms and Conventions @code-idioms-and-conventions.md
  • Project Structure — Go Backend @references/project-structure.md
  • Security Principles @security-principles.md
  • Architectural Patterns — Testability-First Design @architectural-pattern.md
  • Testing Strategy @testing-strategy.md
  • Error Handling Principles @error-handling-principles.md
  • Concurrency and Threading Principles @concurrency-and-threading-principles.md
  • Logging and Observability Mandate @logging-and-observability-mandate.md
  • Logging and Observability Principles @.agents/skills/logging-implementation/SKILL.md
  • Dependency Management Principles @dependency-management-principles.md

© irahardianto, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 3 other files (references) in .agents/skills/go-idioms of irahardianto/awesome-agv.

  • SKILL.md
  • references/go-patterns-and-anti-patterns.md
  • references/project-structure.md
  • references/recommended-dependencies.md

Open the folder on GitHubat commit 9e997ba

Compare with similar skills

Go Idioms next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Go Idioms compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Go Idioms this skillirahardianto/awesome-agv156—~6.3kAutomated safety check: PassMIT
Golang Patternsantoniopaya22/go-rest-template1729 repos~3.5kAutomated safety check: PassNone
GolangJanDeDobbeleer/oh-my-posh24k—~705Automated safety check: PassMIT
Valgocohesivestack/valgo508—~2.4kAutomated safety check: PassMIT
Context Handling in fp-goIBM/fp-go2k—~4.2kAutomated safety check: PassApache-2.0
Typed Dependencies with fp-go EffectIBM/fp-go2k—~4.3kAutomated safety check: PassApache-2.0

Similar skills

  • Golang Patterns

    antoniopaya22/go-rest-template

    Idiomatic Go patterns, best practices, and conventions for building robust, efficient, and maintainable Go applications.

    172 GitHub starsUsed in 9 repos~3.5k tokens
    DevelopmentAuto-check passed
  • Golang

    JanDeDobbeleer/oh-my-posh

    Go conventions for this project that differ from common Go practice.

    24k GitHub stars~705 tokensUpdated today
    DevelopmentAuto-check passed
  • Valgo

    cohesivestack/valgo

    Add, refactor, debug, review, explain, or migrate type-safe validation in consumer Go applications using github.com/cohesivestack/valgo.

    508 GitHub stars~2.4k tokensUpdated 1 mo ago
    DevelopmentAuto-check passed
  • Official

    Covers handling Go's context.Context idiomatically in fp-go code: reading and scoping context through operators, timeouts, cancellation and converting ctx-first functions.

    2k GitHub stars~4.2k tokensUpdated today
    DevelopmentAuto-check passed
  • Teaches an agent to write fp-go v2 services with the Effect type, carrying dependencies in its type parameter instead of in context.Context or parameters.

    2k GitHub stars~4.3k tokensUpdated today
    DevelopmentAuto-check passed
  • Gives an agent working in a Go codebase a structural view through a local MCP server: call graphs, blast-radius and impact analysis, and bounded first-call exploration.

    229 GitHub stars~4.8k tokensUpdated today
    DevelopmentAuto-check: notes

More from irahardianto/awesome-agv

All 34 skills in this repo
  • Distinctive Frontend Design Builder

    irahardianto/awesome-agv

    Commits to one bold aesthetic direction, sets up a CSS token system for it, then builds the interface in Vue or plain HTML using those tokens.

    156 GitHub stars~2.4k tokensUpdated 6 days ago
    Auto-check passed
  • Perf Optimization

    irahardianto/awesome-agv

    Profile-driven performance optimization protocol. An agent skill from irahardianto/awesome-agv.

    156 GitHub stars~4.3k tokensUpdated 6 days ago
    Auto-check passed
  • Angular Idioms and Patterns

    irahardianto/awesome-agv

    Coding conventions for Angular 19 and later: standalone components, signals, OnPush change detection, lazy routes and where RxJS still belongs.

    156 GitHub stars~3.8k tokensUpdated 6 days ago
    Auto-check passed
  • CI/CD Pipeline Principles

    irahardianto/awesome-agv

    Rules for designing CI/CD pipelines in layers: universal lint, test and scan stages, container builds with SBOM attestation, and GitOps for orchestrated deployments.

    156 GitHub stars~2.7k tokensUpdated 6 days ago
    Auto-check: notes
  • Hono Idioms

    irahardianto/awesome-agv

    Hono lightweight web framework patterns: type-safe route handlers, middleware composition, Zod validation, and RPC clients for Cloudflare Workers, Node, or Bun.

    156 GitHub stars~3k tokensUpdated 6 days ago
    Auto-check passed
  • Mobile Testing

    irahardianto/awesome-agv

    Mobile E2E testing patterns — Flutter integrationtest, Patrol, Maestro, golden testing, device matrix, and test data management.

    156 GitHub stars~1.8k tokensUpdated 6 days ago
    Auto-check: notes

Works with

Categories

Questions about Go Idioms

What does Go Idioms do?

Go idioms and patterns: stdlib conventions, explicit error wrapping (%w), small interfaces, goroutines/channels concurrency, table-driven tests, and gofumpt formatting. Go Idioms is an agent skill from irahardianto/awesome-agv. Go idioms and patterns: stdlib conventions, explicit error wrapping (%w), small interfaces, goroutines/channels concurrency, table-driven tests, and gofumpt formatting.

When should I use Go Idioms?

Go Idioms fits situations like: reviewing Go services and packages; tasks that involve Async programming; tasks that involve Refactoring.

How do I install Go Idioms in Claude Code?

Run `npx skills add irahardianto/awesome-agv --skill go-idioms -a claude-code`. Or copy the skill folder (.agents/skills/go-idioms in irahardianto/awesome-agv) into .claude/skills/go-idioms in your project. Claude Code loads it when a task matches its description.

How do I install Go Idioms in Codex?

Run `npx skills add irahardianto/awesome-agv --skill go-idioms -a codex`. Or copy the skill folder (.agents/skills/go-idioms in irahardianto/awesome-agv) into .agents/skills/go-idioms in your project. Codex loads it when a task matches its description.

Can I use Go Idioms in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add irahardianto/awesome-agv --skill go-idioms -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/go-idioms, .gemini/skills/go-idioms, .github/skills/go-idioms and .opencode/skills/go-idioms in your project.

What does Go Idioms need to run?

Going by SKILL.md and its folder, Go Idioms needs the command-line tools its instructions call (go).

Does Go Idioms access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Go Idioms safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Go Idioms use?

Go Idioms is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Go Idioms use?

About 6.3k tokens (SKILL.md is roughly 25k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 9k tokens, read only when the agent opens those files.

What are the alternatives to Go Idioms?

Skills that share tags, products or a category with Go Idioms: Golang Patterns (antoniopaya22/go-rest-template, 172 stars), Golang (JanDeDobbeleer/oh-my-posh, 24k stars), Valgo (cohesivestack/valgo, 508 stars) and Context Handling in fp-go (IBM/fp-go, 2k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Go Idioms?

irahardianto (a GitHub user) maintains it in irahardianto/awesome-agv, which has 156 GitHub stars. The repository holds 34 skills in this directory. The repository was last updated on October 5, 2026.

Source: irahardianto/awesome-agv on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.