Idiomatic Go - package and interface design, error wrapping, table-driven tests, generics, the modern standard library (slices/maps/cmp/errors.Join), current syntax, and logging discipline.

Apache-2.0Auto-check passedDevelopment

Install Go

skills CLI
$ npx skills add inference-gateway/inference-gateway --skill go -a claude-code

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

GitHub CLI
$ gh skill install inference-gateway/inference-gateway go --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/inference-gateway/inference-gateway.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/go .claude/skills/go && 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
GitHub stars
214
Token cost
~2.4k tokens
SKILL.md length
913 words
Files
1
Skills in repo
3
Repo updated
First seen
Licence
Apache-2.0

At a glance

Idiomatic Go - package and interface design, error wrapping, table-driven tests, generics, the modern standard library (slices/maps/cmp/errors.Join), current syntax, and logging discipline.

  • Works in 4 steps: The edit didn't fix the actual logic. → It was in the wrong file, function, or… → A second call site has the same bug,… → …
  • Refactoring any Go code
  • SKILL.md covers Core principles, Packages: flat, named for what…, Interfaces: discovered, not… and Errors are values, plus 7 more sections
  • Calls go

What it does

Go is an agent skill from inference-gateway/inference-gateway. Idiomatic Go - package and interface design, error wrapping, table-driven tests, generics, the modern standard library (slices/maps/cmp/errors.Join), current syntax, and logging discipline. Use when writing, reviewing, or refactoring any Go code, especially code drifting toward Java/Spring shapes (deep layer trees, generic repositories, heavy frameworks) - even if the user never says "idiomatic". Distilled from spf13/go-skills and adapted to this repo.

Its SKILL.md is about 2.4k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Development, covering API design and Refactoring. It works with Java, DeepSeek, Model Context Protocol and OpenAI. The repository describes itself as: An open-source, cloud-native, high-performance gateway unifying multiple LLM providers, from local solutions like Ollama to major cloud providers such as OpenAI, Groq, Cohere… The licence is Apache-2.0.

When your agent uses it

  • Refactoring any Go code
  • Especially code drifting toward Java/Spring shapes (deep layer trees
  • Generic repositories
  • Heavy frameworks) - even if the user never says idiomatic

Example prompts

  • “idiomatic”
  • “/go”

Workflow steps

4 steps, taken from the first numbered list in SKILL.md.

  1. The edit didn't fix the actual logic.
  2. It was in the wrong file, function, or package.
  3. A second call site has the same bug, unfixed.
  4. The error comes from a different code path than you edited.

What it can do on your machine

Read from SKILL.md and the folder at commit 49d1f12. 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

    Links to these hosts (documentation or services it may open):

    • github.com

    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 loads about 2.4k tokens when it runs. Until then it costs about 115 tokens; SKILL.md has 913 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~115
When it runs · the whole SKILL.md, loaded when a task matches
~2.4k

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 inference-gateway/inference-gateway at commit 49d1f12, republished under its Apache-2.0 licence (© inference-gateway). 913 words, ~2,442 tokens.

Download SKILL.mdSave it as .claude/skills/go/SKILL.md (or your agent's skills folder).
name
go
description
Idiomatic Go - package and interface design, error wrapping, table-driven tests, generics, the modern standard library (slices/maps/cmp/errors.Join), current syntax, and logging discipline. Use when writing, reviewing, or refactoring any Go code, especially code drifting toward Java/Spring shapes (deep layer trees, generic repositories, heavy frameworks) - even if the user never says "idiomatic". Distilled from spf13/go-skills and adapted to this repo.
license
Apache-2.0

Idiomatic Go

Write Go that is boring in the best way - direct, predictable, obvious on the first read. Clear is better than clever. The common failure mode (and the LLM default) is importing Java/Spring habits - deep layer trees, generic repositories, heavy frameworks, manual worker pools - into a language built for flat, simple, discoverable APIs. When in doubt, delete the abstraction.

Core principles

Clear is better than clever. If a function's control flow takes three reads to follow, rewrite it. Keep the happy path un-indented: handle errors and edge cases first and return.

go
func GetUser(id string) (*User, error) {
    user, err := db.FindUser(id)
    if err != nil {
        return nil, fmt.Errorf("finding user %s: %w", id, err)
    }
    return user, nil // happy path stays at the left margin
}

Make the zero value useful. Design types so the zero value works without a constructor - sync.Mutex and bytes.Buffer are the gold standard.

go
type Counter struct {
    mu    sync.Mutex // usable at the zero value - no New() needed
    count int
}

func (c *Counter) Inc() { c.mu.Lock(); c.count++; c.mu.Unlock() }

Packages: flat, named for what they do

Start flat; add a package only when a domain earns a namespace. Name packages by what they do (auth, billing, jobs), never by what layer they are (service, repository, controller) - layer-named packages breed circular imports and interface bloat and add zero clarity in Go. No utils/, helpers/, or common/ junk drawers; they signal unclear ownership. Packages don't import each other sideways - cycles mean wrong boundaries; the composition root wires them.

In this repo: code lives under internal/ in a deliberate domain (pure interfaces) / infra (adapters) / services (business logic) split, wired by a DI container (internal/container/container.go). That is this project's structure - follow it; don't "flatten internal/." spf13's transferable rules still hold: name by purpose, no junk-drawer packages, wire at the composition root (here, the container).

Interfaces: discovered, not designed

Write concrete types first. Introduce an interface only when a consumer genuinely needs to swap implementations, and define it in the consuming package, kept small (io.Reader, not *os.File). Accept interfaces, return structs - callers get the narrow dependency they need without type-asserting to reach real fields.

go
// the consumer declares exactly what it needs; the concrete store needn't know
type UserFetcher interface {
    GetUser(id string) (*User, error)
}

type Processor struct{ fetcher UserFetcher }

In this repo: domain contracts are centralized in internal/domain/interfaces.go so counterfeiter can generate fakes from one place - that's the established seam. Still prefer small interfaces; just declare new ones there when they need a generated mock.

Errors are values

Check them explicitly; they aren't exceptions. Wrap with %w to add context while preserving the chain for errors.Is / errors.As. Combine siblings with errors.Join (Go 1.20) - no multierr needed.

go
data, err := os.ReadFile(path)
if err != nil {
    return fmt.Errorf("loading config %s: %w", path, err)
}

Functional options for complex construction

When a type has many optional settings, avoid telescoping constructors:

go
type Option func(*Server)

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

func NewServer(addr string, opts ...Option) *Server {
    s := &Server{addr: addr, timeout: 30 * time.Second} // sane defaults
    for _, opt := range opts {
        opt(s)
    }
    return s
}

Testing is just Go

Go testing is just Go programming - reach for the stdlib testing package, not a BDD framework.

  • Table-driven tests with t.Run subtests are the standard.
  • Call t.Helper() in assertion helpers so failures point at the case, not the helper.
  • Prefer simple fakes/stubs for stand-ins - implicit interfaces make them cheap to hand-write.
  • Put fixtures in testdata/ (the tool ignores it); diff large output against golden files.
  • Compare structs with github.com/google/go-cmp/cmp, not reflect.DeepEqual.
  • Abstract the filesystem with afero and inject afero.NewMemMapFs() in tests.
go
func TestParse(t *testing.T) {
    tests := []struct {
        name    string
        in      string
        wantErr bool
    }{
        {"valid", "port=8080", false},
        {"bad", "port=abc", true},
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            _, err := Parse(tt.in)
            if (err != nil) != tt.wantErr {
                t.Fatalf("Parse(%q) err = %v, wantErr %v", tt.in, err, tt.wantErr)
            }
        })
    }
}

In this repo: fakes for domain interfaces are counterfeiter-generated under tests/mocks/, not hand-written. Regenerate with task mocks:generate (pre-commit runs it when internal/domain/interfaces.go changes); for a new domain interface, add a counterfeiter line under mocks:generate in Taskfile.yml. Use the generated fakes - don't hand-roll rivals. Table tests, testdata, and go-cmp still apply.

Show full SKILL.md (403 more words)Show less

Use current Go, not 2018 Go

This repo targets Go 1.26 - reach for the modern stdlib before any third-party helper or hand-rolled loop:

Instead ofUse
sort.Slice(s, ...)slices.Sort(s), slices.SortFunc, slices.Contains/Index
manual key/value loopsmaps.Keys/Values/Clone/Copy/Equal
if x == 0 { x = def }cmp.Or(x, def); min/max built-ins
ad-hoc multi-error joinserrors.Join(err1, err2)
atomic.AddInt64(&n, 1)typed atomic.Int64/Bool/Pointer[T] (n.Add(1))
gorilla/mux for basic routingnet/http: mux.HandleFunc("GET /u/{id}", ...) + r.PathValue("id")
for i := 0; i < n; i++for i := range n
interface{}any
// +build tags//go:build

To keep a request's values but drop its cancellation for work that outlives it, use context.WithoutCancel(ctx) (Go 1.21).

Generics eliminate duplication, not model hierarchies

Use a generic when the same algorithm runs over many concrete types.

go
func Map[S, T any](s []S, f func(S) T) []T {
    out := make([]T, len(s))
    for i, v := range s {
        out[i] = f(v)
    }
    return out
}

Do not write generic "repositories", services, or base types - that's Java in Go syntax. Use comparable for map keys/equality and cmp.Ordered for </>. Start concrete; generify only once the same logic repeats across 3+ types.

Logging discipline

go
logger.Debug("cache miss", "key", key)      // high-volume internal state
logger.Info("server started", "addr", addr) // lifecycle events
logger.Warn("retrying", "attempt", n)        // recoverable problems
logger.Error("request failed", "err", err)   // needs attention
  • Inject the logger as a dependency; no package-level logger beyond main.
  • Never log and return the same error - log once at the boundary, return it up the stack everywhere else.

In this repo: logging is go.uber.org/zap (*zap.Logger, from the container's Logger()), not slog. The discipline above is identical.

Concurrency, briefly

  • Share memory by communicating - pass data over a channel instead of guarding it with a mutex where you can. Channels orchestrate; mutexes serialize.
  • Bound concurrency with a buffered-channel semaphore, not a static worker pool (Go's scheduler is cheap):
go
func FetchAll(ctx context.Context, urls []string, max int) error {
    sem := make(chan struct{}, max)
    g, ctx := errgroup.WithContext(ctx)
    for _, u := range urls {
        sem <- struct{}{} // blocks at the limit
        g.Go(func() error {
            defer func() { <-sem }()
            return fetch(ctx, u)
        })
    }
    return g.Wait()
}
  • Never start a goroutine without knowing how it stops - every go func() needs a ctx/closed-channel exit, or it leaks.

For channel patterns in depth - done-channel, fan-out/fan-in, pipeline, or-done, context propagation, worker semaphore - see the go-concurrency skill, and verify with go test -race.

Debugging: the Go toolchain is not the bug

go build/test/run are deterministic and the build cache is keyed by source - don't suspect them or reach for go clean -cache. When an error survives your edit, it's almost always one of these, in order:

  1. The edit didn't fix the actual logic.
  2. It was in the wrong file, function, or package.
  3. A second call site has the same bug, unfixed.
  4. The error comes from a different code path than you edited.

Re-read the (accurate) error, confirm the file is actually compiled (go list -f '{{.GoFiles}}' .), and add a t.Log/print at the exact site.


Adapted from spf13/go-skills (MIT, by Steve Francia), trimmed and reconciled with this repo's conventions. Pairs with go-concurrency, cobra-viper, and go-spec-reviewer.

© inference-gateway, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .agents/skills/go of inference-gateway/inference-gateway.

Open the folder on GitHubat commit 49d1f12

Compare with similar skills

Go 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 compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Go this skillinference-gateway/inference-gateway214—~2.4kAutomated safety check: PassApache-2.0
Code Qualitypiomin/claude-ai-spring-boot1.3k—~2.2kAutomated safety check: PassApache-2.0
Bootui Java Developmentjdubois/boot-ui311—~1.3kAutomated safety check: PassApache-2.0
Azsdk Common Generate SDK LocallyAzure/azure-sdk-for-android121—~1.5kAutomated safety check: PassMIT
Idea MCPdtprj/dongting208—~698Automated safety check: PassApache-2.0
Edt MCP ArchitectureDitriXNew/EDT-MCP295—~1.2kAutomated safety check: PassAGPL-3.0

Similar skills

  • Code Quality

    piomin/claude-ai-spring-boot

    Comprehensive code review for Java - clean code principles, API contracts, null safety, exception handling, and performance.

    1.3k GitHub stars~2.2k tokensUpdated 5 mo ago
    DevelopmentAuto-check passed
  • A skill your agent uses when implementing, debugging, refactoring, or testing existing BootUI Java code, including framework-neutral engine logic, Spring MVC and WebFlux adapters, Quarkus runtime…

    311 GitHub stars~1.3k tokensUpdated today
    DevelopmentAuto-check passed
  • Azsdk Common Generate SDK Locally

    Azure/azure-sdk-for-android

    Official

    Generate, build, and test Azure SDKs locally from TypeSpec with automatic customization.

    121 GitHub stars~1.5k tokensUpdated 4 mo ago
    Backend & APIsAuto-check passed
  • Idea MCP

    dtprj/dongting

    IntelliJ IDEA MCP for Java code analysis, testing, refactoring, and project navigation.

    208 GitHub stars~698 tokensUpdated today
    DevelopmentAuto-check passed
  • Edt MCP Architecture

    DitriXNew/EDT-MCP

    Map of the EDT-MCP plugin's target architecture — where the shared helpers live, the layering rules, and the canonical way to do project/metadata/code resolution.

    295 GitHub stars~1.2k tokensUpdated yesterday
    Agent WorkflowsAuto-check passed
  • Opentelemetry

    grafana/skills

    Official

    Instrument any app with OpenTelemetry and ship metrics / logs / traces to Grafana Cloud or self-hosted Mimir / Loki / Tempo / Pyroscope.

    281 GitHub stars~1.7k tokensUpdated today
    DevOps & CloudAuto-check passed

More from inference-gateway/inference-gateway

  • Go Concurrency

    inference-gateway/inference-gateway

    Idiomatic Go concurrency - sync primitives, channel semantics, the select statement, and the standard channel patterns (cancellation/done-channel, fan-out/fan-in, pipeline, or-done, context…

    214 GitHub stars~2.3k tokensUpdated today
    Auto-check passed
  • Go Spec Reviewer

    inference-gateway/inference-gateway

    Review a Go design spec before implementation begins - dispatch a subagent that checks a design doc for completeness, consistency, and idiomatic Go (simplicity, small consumer-defined interfaces…

    214 GitHub stars~1.2k tokensUpdated today
    Auto-check passed

Questions about Go

What does Go do?

Idiomatic Go - package and interface design, error wrapping, table-driven tests, generics, the modern standard library (slices/maps/cmp/errors.Join), current syntax, and logging discipline. Go is an agent skill from inference-gateway/inference-gateway.Join), current syntax, and logging discipline.

When should I use Go?

Go fits situations like: refactoring any Go code; especially code drifting toward Java/Spring shapes (deep layer trees; generic repositories; heavy frameworks) - even if the user never says idiomatic.

How do I install Go in Claude Code?

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

How do I install Go in Codex?

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

Can I use Go 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 inference-gateway/inference-gateway --skill go -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, .gemini/skills/go, .github/skills/go and .opencode/skills/go in your project.

What does Go need to run?

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

Does Go access the network?

SKILL.md names 1 domain. As links in the text: github.com. This is read from the text; nothing was executed.

Is Go 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 use?

Go is published under the Apache-2.0 licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Go use?

About 2.4k tokens (SKILL.md is roughly 9.8k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Go?

Skills that share tags, products or a category with Go: Code Quality (piomin/claude-ai-spring-boot, 1.3k stars), Bootui Java Development (jdubois/boot-ui, 311 stars), Azsdk Common Generate SDK Locally (Azure/azure-sdk-for-android, 121 stars) and Idea MCP (dtprj/dongting, 208 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Go?

inference-gateway (a GitHub organization) maintains it in inference-gateway/inference-gateway, which has 214 GitHub stars. The repository holds 3 skills in this directory. The repository was last updated on October 8, 2026.

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