Effective Go as a Living Standard
Go ships an official style and idiom guide called Effective Go.
Search across all documentation pages
Go ships an official style and idiom guide called Effective Go.
It predates modules, generics, and modern observability stacks, yet it still anchors how experienced Go developers read code.
Community rules and checklists extend that document into enforceable habits for teams shipping libraries and services today.
The Go team published Effective Go alongside the language to teach idioms, not syntax.
It covers formatting, naming, control flow, data structures, initialization, methods, interfaces, embedding, concurrency, and the standard library's flavor.
It is not a specification.
The compiler does not enforce most of its advice.
gofmt is the one hard rule baked into the toolchain: readable diffs and zero formatting bikeshedding.
Everything else lives on a spectrum from automated (vet, staticcheck) to cultural (when to use a pointer receiver, how much to export).
Community material fills gaps Effective Go never aimed to cover.
Module semver policy, gRPC handler layout, Kubernetes controller patterns, and security baselines appear in team guides and site checklists.
Those documents cite Effective Go as foundation, then add operational context.
Think of three layers:
Layer 1 Effective Go + official release notes (what the language means)
Layer 2 Community guides + linters (what teams enforce)
Layer 3 Your ADRs + checklists (what this repo requires)A living standard updates Layer 2 and 3 when Go minors ship new vet checks, go fix modernizers, or stdlib deprecations.
Layer 1 changes slowly and stays the north star.
Rules interact with tooling in predictable ways.
Objective rules - formatting, suspicious printf verbs, unreachable code - belong in CI.
Subjective rules - interface size, package naming, error message tone - belong in review rubrics backed by short checklists.
When a rule repeats in three PR comments, promote it: add a linter rule, a //nolint exception process, or an ADR.
When a rule blocks a measured optimization, document the exception with a benchmark or incident link.
Effective Go's concurrency section emphasizes channels for communication, mutexes for state.
Community concurrency checklists add ownership: who creates a channel, who closes it, where context cancels work.
Those additions prevent data races the original essay did not spell out for HTTP servers and worker pools.
Library authors face stricter API rules than application authors.
Exported symbols are compatibility promises under semver.
Effective Go's naming guidance becomes a breaking-change policy: renaming an exported func is a major bump.
Services add security and performance rules Effective Go only hints at: validate inputs at boundaries, measure before tuning GC.
| Audience | Primary rule sources | Enforcement |
|---|---|---|
| New learner | Effective Go, tour, fundamentals pages | gofmt, small exercises |
| Application team | Site checklists, review standards | CI + PR template |
| Library maintainer | API design rules, semver, godoc | staticcheck API checks, tag review |
| Platform / SRE | Security, observability, module policy | govulncheck, dependency gates |
Major Go releases can obsolete a team rule overnight.
Go 1.22 loop variable capture fixes removed a class of "copy the loop var" review nits.
go fix modernizers (Go 1.26+) may rewrite patterns your old style guide forbade.
Schedule a quarterly rule audit: read release notes, rerun linters with new defaults, retire ADRs that only existed for fixed compiler bugs.
Monorepos with multiple modules often need tiered rules.
A shared platform/ module stays conservative on exports.
An internal cmd/ experiment tolerates faster iteration.
Document tiers in the section summary page so contributors know which checklist applies.
Open-source consumers of your rules should distinguish portable idioms (errors, context, formatting) from org-specific choices (logging library, RPC framework).
Portable content belongs in public style guides.
Org choices belong in internal ADRs linked from README.
International teams benefit from translating rule intent, not literal English error strings.
Effective Go's examples use English prose; your production rules should still require wrapped errors and structured logs without mandating a single phrasing.
The spec defines what compiles.
Effective Go teaches how experienced developers write readable, maintainable code.
Neither replaces the other.
Link to go.dev/doc/effective_go as source of truth.
Add a short delta doc for rules that go beyond it (HTTP timeouts, module policy).
Avoid stale copies that diverge silently.
Guides like Uber's or Google's compile team experience into tables and examples.
They cite the same idioms - errors, naming, concurrency - with stricter operational defaults.
Treat them as Layer 2, not competing authorities.
gofmt/goimports, go vet ./..., go test ./..., then golangci-lint presets and govulncheck.
Match Code Quality Basics before adopting long checklists.
After every Go minor upgrade and when a repeated review comment appears three times in a sprint.
Small, dated ADRs beat annual style-guide rewrites.
Libraries emphasize stable exported APIs, minimal dependencies, and semver.
Services emphasize observability, security boundaries, and deployment config.
Both share formatting, errors, and context conventions.
Prefer clear type parameters over empty interfaces when constraints express capability.
Effective Go's interface advice still applies: keep interfaces small and defined by consumers.
They accelerate enforcement.
New contributors still need Effective Go's why to make judgment calls linters cannot encode.
Templates ask authors to confirm tests, migrations, and rollbacks.
Checklists teach reviewers what to verify.
Link both to the same rule pages to avoid drift.
Apply rules to touched lines and new packages first.
Use ratcheting linters and exclude directories with sunset dates, not permanent silence.
Exported API error text is part of compatibility.
Use stable sentinel errors and wrap with context; avoid baking product copy into library errors.
Some stdlib and concurrency rules assume full runtime.
Scope checklists per build tag and document excluded linters for embedded targets.
Stack versions: This page was written for Go 1.26.x (Green Tea GC default, go fix modernizers - verify patch at build), chi (latest - verify at build), gin (latest - verify at build), echo (latest - verify at build), google.golang.org/grpc (latest - verify at build), sigs.k8s.io/controller-runtime (latest - verify at build), kubebuilder (latest - verify at build), tinygo (latest - verify board targets at build), wazero (latest - verify at build), and golangci-lint (latest - verify linter set at build).
Reviewed by Chris St. John·Last updated Jul 16, 2026