agentsclimarketplace

Go idiomatic discipline

Skill ctoth/golang-skills-plugin/plugins/golang/skills/go-idiomatic-discipline

Agent skill plugins for Go code quality and performance work.

Install
npx -y skills add ctoth/golang-skills-plugin --skill go-idiomatic-discipline

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Guides core Go authoring discipline along two axes — handle errors honestly and stop fighting the language on the floor (no discarded errors, no panic for ordinary failure, no Java/Python-in-Go), and don't over-abstract or out-clever it on the ceiling (no interface-per-struct, no premature generics, no framework scaffolding for a small tool). The judgment target is "clear AND correct." Auto-invokes when writing or editing .go files, and on "make it idiomatic", "is this idiomatic Go", or "clean this up" requests. The dual-axis policy root every other Go skill routes back to.

SKILL.md

13.4 KB, as published. Nobody here has run it

Go Idiomatic Discipline

"Clear is better than clever." — Go Proverbs

"Errors are values." · "Don't just check errors, handle them gracefully." · "Don't panic." — Go Proverbs

"A straightforward translation of a C++ or Java program into Go is unlikely to produce a satisfactory result—Java programs are written in Java, not Go." — Effective Go

Idiomatic Go is not a matter of taste. The language has a small, opinionated grain, and code either runs with it or fights it. There are two opposite ways to fight it, and this skill bans both.


1. The Two Failure Modes

Writing Go well means landing between two opposite mistakes. Both compile. Both ship. Both are wrong.

Axis 1 — too sloppy / fighting Go (the floor)

Under time pressure the model writes Java- or Python-in-Go: it silences the compiler and the runtime instead of working with them. It discards an error with _, reaches for panic on an ordinary failure, wraps everything in getter/setter classes, builds OOP inheritance fantasies, and stashes mutable state in package globals. Each is the Go-native equivalent of an escape hatch — the program looks finished, but a real failure is now invisible. Go's own guidance is blunt that this is the wrong move: "A straightforward translation of a C++ or Java program into Go is unlikely to produce a satisfactory result" (Effective Go); "to write Go well, it's important to understand its properties and idioms" (Effective Go).

Axis 2 — too clever / over-abstracted (the ceiling)

Asked to "make it idiomatic" or "make it robust," the model over-builds to look thorough: an interface for every struct, generics with a single caller, a constructor that only zeroes fields, a 200-line clever generic, deep framework scaffolding around a 50-line tool. Every Go Proverb on the page pushes the other way: "Clear is better than clever"; "The bigger the interface, the weaker the abstraction"; "A little copying is better than a little dependency"; "interface{} says nothing" (Go Proverbs). Abstraction that no second implementation justifies is a cost with no buyer.

This skill names both axes and states the headline rules. Depth routes to the specific skills (Section 8).


2. The Meta-Rule: Clear AND Correct

The judgment target is code that is both clear and correct.

  • Code that ignores an error or panics on ordinary failure is incorrect — that is axis 1.
  • Code that is correct but needlessly abstract or clever is also wrong — that is axis 2. It compiles, it ships, and it is still a wrong answer because the next reader pays for it.

The Google Go Style Guide ranks the attributes of readable code "in order of importance": clarity, simplicity, concision, maintainability, consistency (Google Go Style Guide — Guide). Clarity is first, and its companion rule is least mechanism: "Where there are several ways to express the same idea, prefer the one that uses the most standard tools" (Google Go Style Guide — Guide).

When you author or review Go, both questions must pass:

  1. Is it correct? Is every error handled, every goroutine stoppable, every failure surfaced — not swallowed?
  2. Is it clear? Would the simplest reader on the team follow it? Is every abstraction earned by a real second caller, or is it scaffolding?

"Make it idiomatic" is satisfied only when both hold.


3. The Headline Disciplines

Each rule below is stated here as policy; the owning skill (Section 8) holds the depth.

DisciplineThe ruleSource
Errors are valuesNever discard with _; check, handle, or return — wrap with %w"Errors are values" (Proverbs); "Do not discard errors using _ variables" (CodeReviewComments)
Don't panicpanic is for programmer bugs, not ordinary failure"Don't use panic for normal error handling. Use error and multiple return values" (CodeReviewComments)
Line of sightHappy path at minimal indent; handle the error first and return"keep the normal code path at a minimal indentation, and indent the error handling, dealing with it first" (CodeReviewComments)
No Get gettersA getter for owner is Owner(), not GetOwner()"it's neither idiomatic nor necessary to put Get into the getter's name" (Effective Go)
Small, consumer-side interfacesDefine interfaces where they're used, not per struct"The bigger the interface, the weaker the abstraction" (Proverbs); "Do not define interfaces before they are used" (CodeReviewComments)
Don't reach for generics firstUse an interface for behavior; reach for type params only on real duplication"You should avoid type parameters until you notice that you are about to write the exact same code multiple times" (When To Use Generics)
Make the zero value usefulAvoid constructors that only zero fields"Make the zero value useful" (Proverbs)
No mutable package globalsConfigure with arguments and fields, not exported globals"prefer explicit function arguments or struct field assignment or ... under the strictest of scrutiny exported global variables" (Google Go Style Guide — Decisions)
Gofmt decidesDon't hand-format; run gofmt/gofumpt"Gofmt's style is no one's favorite, yet gofmt is everyone's favorite" (Proverbs)

4. The Headline Rule: Errors Are Values, Never Silently Discarded

The single highest-frequency Go failure is the swallowed error. The Go Proverbs state it twice — "Errors are values" and "Don't just check errors, handle them gracefully" (Go Proverbs) — and Code Review Comments makes it a hard rule: "Do not discard errors using _ variables. If a function returns an error, check it to make sure the function succeeded. Handle the error, return it, or, in truly exceptional situations, panic" (CodeReviewComments).

// WRONG — the error is discarded; a malformed payload becomes a silent empty struct
var cfg Config
_ = json.Unmarshal(data, &cfg)
return cfg

// RIGHT — check it, add context, return it; line of sight keeps the happy path flat
var cfg Config
if err := json.Unmarshal(data, &cfg); err != nil {
	return Config{}, fmt.Errorf("parsing config: %w", err)
}
return cfg, nil

Because errors are ordinary values, "the full power of the Go programming language is available for processing them" (Errors are values) — but the floor is non-negotiable: "Whatever you do, always check your errors!" (Errors are values). This skill states the floor; go-error-handling owns the depth: %w wrapping, errors.Is/As, sentinel vs typed errors, errors.Join, and message conventions.


5. Don't Fight Go (Axis 1 in Brief)

The recurring tells of Java/Python-in-Go, each routed to its owning skill:

  • Discarded errors / panic for ordinary failure — see Section 4 and go-error-handling, go-defer-panic-recover. "Don't use panic for normal error handling" (CodeReviewComments).
  • Get-prefixed getters and getter/setter classes — the field owner is read with Owner(), not GetOwner() (Effective Go). Use Counts over GetCounts (Google Go Style Guide — Decisions). Owned by go-naming-and-style.
  • OOP inheritance fantasies — Go composes with embedding and satisfies interfaces structurally; there is no class hierarchy to port. Owned by go-interfaces, go-zero-values-and-construction.
  • Mutable package globals — prefer arguments and struct fields (Google Go Style Guide — Decisions). Owned by go-zero-values-and-construction.
  • Leaked goroutines — never start one you can't stop; tie it to a context or a WaitGroup. Owned by go-concurrency-goroutines.

6. Don't Out-Clever Go (Axis 2 in Brief)

The recurring tells of over-abstraction, each routed to its owning skill:

  • Interface pollution — one interface mirroring a struct's whole method set, defined on the producer side "for mocking." "Do not define interfaces on the implementor side of an API"; "Do not define interfaces before they are used" (CodeReviewComments). "The bigger the interface, the weaker the abstraction" (Proverbs). Owned by go-interfaces.
  • Premature generics — type parameters with one caller, where an interface or a concrete type reads better. "If all you need to do with a value of some type is call a method on that value, use an interface type, not a type parameter" (When To Use Generics). Owned by go-generics.
  • Needless constructors — a New that only returns &T{}; prefer a useful zero value. "Make the zero value useful" (Proverbs). Owned by go-zero-values-and-construction.
  • Framework scaffolding for a small tool — a deep pkg//internal//api/ tree and util/common grab-bags around a 50-line program. "A little copying is better than a little dependency" (Proverbs). Owned by go-project-layout.

7. Who Suffers When Go Is Done Badly

Both axes have a victim, and it is never the author at write time:

  • The on-call engineer paged at 3am by a goroutine leak that exhausted memory — started by a library that spawned work the caller couldn't stop (axis 1).
  • The teammate who loses an afternoon to a bug whose root cause was a _ = err three layers down that swallowed the only diagnostic (axis 1).
  • The reviewer who has to reverse-engineer a 200-line clever generic, or an interface-per-struct mock maze, to make a one-line change (axis 2).

"Clear is better than clever" (Proverbs) is an empathy rule, not an aesthetic one: the clever version offloads cost onto whoever reads the code next. Idiomatic Go is what you write so that nobody downstream pays for your shortcut or your showmanship.


8. Routing to the Specific Skills

This skill is the policy. The specific applications live in the other Go skills:

Axis 1 — correctness (don't fight Go; don't swallow failure):

  • go-error-handling%w wrapping, errors.Is/As, sentinel vs typed, errors.Join, message strings. The depth behind Section 4.
  • go-defer-panic-recoverdefer mechanics, when panic is legitimate, recover only at a boundary.
  • go-concurrency-goroutines / go-context — goroutine lifetime and cancellation; the leak in Section 7.
  • go-interfaces — accept interfaces / return structs, and the typed-nil-error gotcha.
  • go-zero-values-and-construction — useful zero values, constructors/options, no mutable globals.

Axis 2 — restraint and design (don't over-build):

  • go-interfaces — interface pollution, consumer-side placement, small -er interfaces.
  • go-generics — the "don't reach first" rule and when type params earn their place.
  • go-project-layoutinternal/, cmd/, no util/common grab-bags, keep main thin.
  • go-naming-and-style — MixedCaps, initialisms, no Get getters, short receivers, line of sight, doc comments.

Detection:

  • go-tooling-and-static-analysisgofmt/gofumpt, go vet, staticcheck, golangci-lint, govulncheck: the CI gate that detects violations of the rules above (a discarded error or a copied lock is found by the toolchain, not by reading one file).
  • go-version-feature-map — which idiom the module's go directive allows, so "idiomatic" means current idiomatic.

9. Reference Files

The high-frequency anti-patterns in LLM-generated Go, each with wrong/right code and citations, are in:

${CLAUDE_SKILL_DIR}/references/common-mistakes.md

Source provenance for every claim in this skill:

${CLAUDE_SKILL_DIR}/references/sources.yaml

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.