Coding Standards & Doc Conventions for Teams
Team Go standards translate community idioms into review rules your CI can enforce.
Search across all documentation pages
Team Go standards translate community idioms into review rules your CI can enforce.
This cheatsheet collects the rules senior engineers repeat every sprint so hires and linters align faster.
//nolint must cite ADR id).go vet adds analyzers.| Rule | Enforcement | Rationale |
|---|---|---|
gofmt on save/CI | gofmt -l . fails build | Single official formatter |
goimports ordering | goimports -local github.com/yourco | Stable import blocks |
| Line length ~100-120 | golines or review | Wrapping is gofmt's job, not arbitrary breaks |
| File names | snake_case.go for tests _test.go | Matches stdlib conventions |
| Package layout | cmd/, internal/, pkg/ or domain dirs | Document which pattern your org uses |
| Symbol | Convention | Example |
|---|---|---|
| Packages | short, lowercase, no underscores | billing, not billing_service |
| Interfaces | consumer-defined, -er when natural | type Store interface { Save(...) } in caller pkg |
| Errors | ErrFoo vars, FooError types | var ErrNotFound = errors.New("billing: not found") |
| Constructors | NewT or NewTWithOpts | func NewServer(cfg Config) *Server |
| Test helpers | helper_ prefix or t.Helper() | Avoid exporting test-only symbols |
| Generics | type params short but meaningful | func Map[T, U any](...) |
| Rule | Code pattern | Review trigger |
|---|---|---|
Wrap with %w | fmt.Errorf("load cfg: %w", err) | Bare returns crossing package boundaries |
| Sentinel errors documented | godoc on var Err... | Changing sentinel text is breaking |
context first param | func Fetch(ctx context.Context, id string) | Missing ctx on IO or RPC |
| No panic in libraries | return errors | panic only in main or init misconfig |
%v vs %w | log with %v, wrap with %w | Logging wrapped chain incorrectly |
if err := db.Save(ctx, rec); err != nil {
return fmt.Errorf("billing: save invoice %s: %w", rec.ID, err)
}| Rule | Tooling | Notes |
|---|---|---|
| Table-driven tests | t.Run subtests | Name cases for failure clarity |
-race on CI | go test -race ./... | Required for concurrency pkgs |
| Examples compile | go test runs Example_* | Docs stay honest in CI |
| Coverage targets | team-defined per package tier | Libraries higher than main |
No sleep in tests | use channels, synctest when available | Flaky tests are defects |
| Element | Rule | Example |
|---|---|---|
| Package comment | One per package, package foo block | Explain purpose, not implementation |
| Exported func | Starts with func name | // Parse reads ... for Parse |
| Deprecated | // Deprecated: use NewParse | Link migration issue |
| Parameters | Name in comment when non-obvious | // ctx carries deadline for outbound RPC. |
| Errors section | Document returned errors | // Returns ErrNotFound when ... |
| Example functions | In _test.go, // Output: | Shows up on pkg.go.dev |
// Package billing implements invoice storage for the payments service.
package billing
// Parse reads an invoice ID from raw user input.
// It returns ErrInvalidID when the format is not ULID.
func Parse(id string) (InvoiceID, error)| Linter | Catches | Enable when |
|---|---|---|
govet | stdlib analyzers | Always |
staticcheck | API deprecations, bugs | Always |
errcheck | ignored errors | Always |
ineffassign | dead assignments | Always |
gosec | security smells | Tune false positives per ADR |
revive | style beyond gofmt | Align rules with written guide |
gocritic | opinionated simplifications | After team workshop |
# .golangci.yml excerpt - align with this cheatsheet
linters:
enable:
- govet
- staticcheck
- errcheck
- ineffassign
run:
timeout: 5m| Situation | Standard response | Document |
|---|---|---|
| New external dependency | License + module path review | DEP-ADR |
unsafe or cgo | Second reviewer required | SEC-ADR |
| Breaking exported API | Major version module or internal only | API-ADR |
//nolint | Comment cites rule + ADR | STYLE-ADR |
Ignored go vet | Forbidden without platform approval | TOOL-ADR |
gofmt handles layout only.
Teams still need rules for errors, context, interfaces, and dependency policy.
Use it as a baseline.
Adapt sections where your monorepo constraints differ, and record deltas in ADRs.
Keep type parameters short in small helpers; exported APIs deserve descriptive constraint names.
Document JSON/protobuf tag conventions once.
Enforce via linters (tagalign) if drift is common.
Example functions must be in tests to compile as docs.
Use regular comments for narrative elsewhere.
Prefer gofmt wrapping.
Hard limits matter mostly for generated code exclusions.
Same godoc rules, but exported means "exported to other teams" - still comment stable internal APIs.
Run new linters in warn mode one sprint, then promote to fail.
Yes via make lint mirroring CI.
Authors should not rely on reviewers as linters.
Effective Go is the philosophical source.
This cheatsheet is enforceable team policy derived from it plus your ADRs.
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 19, 2026