Portable Go memory for AI coding agents. This file is intentionally project-agnostic and can be dropped into any Go repository to provide up-to-date (through Go 1.26) guidance on language features, engineering practices, tooling, API design, security, and error handling.
- Respect
go.modas source of truth (module path, Go version, dependency graph). - Keep changes idiomatic and minimal; preserve public API contracts unless asked to break them.
- Always run formatting + tests after code changes.
- Prefer explicit, inspectable error handling over panic.
- Use context correctly in boundaries and concurrent flows.
- If behavior changes, add/adjust tests first or alongside implementation.
- Multi-error wrapping improvements:
errors.Join(...)fmt.Errorfsupports multiple%werrors.Is/errors.Astraverse multi-error trees
contextcancellation causes:WithCancelCause,Causenet/httpResponseController
- Built-ins:
min,max,clear - Structured logging in stdlib:
log/slog - Expanded context utilities:
WithTimeoutCause,WithDeadlineCause,AfterFunc,WithoutCancel - Stronger toolchain/version compatibility controls
forloop variable semantics fixed (per-iteration capture safety)- Integer
range - Expanded
net/httpServeMux patterns (method/wildcard style)
rangeover iterator functionsiterpackage + iterator helpers inmaps/slices- Timer behavior improvements for correctness/GC
- Generic type aliases fully supported
runtime.AddCleanupintroduced (preferred over many finalizer uses)testing.B.Loopfor benchmarksos.Root/os.OpenRootfor safer filesystem scoping
- No major language syntax changes
- Runtime/tooling improvements (e.g.,
runtime/trace.FlightRecorder) - Green Tea GC available as experiment
new(...)accepts expression initializers- More expressive generic constraints
go fixmodernizers revamp- Green Tea GC enabled by default
errors.AsType[E error]for typed generic extraction
- Use Go modules (
go.mod,go.sum) as canonical dependency state. - Prefer
go get/go mod tidyover manual editing for dependency changes. - Keep
go.modminimal and accurate; remove dead dependencies regularly. - Understand and use
replace/exclude/retractintentionally. - Treat
godirective as minimum supported toolchain behavior contract.
- Enforce canonical formatting with
gofmt(go fmt ./...). - Keep code simple, explicit, and readable over clever.
- Follow standard Go naming and export conventions.
context.Contextshould be first parameter where required.- Never pass nil context (
context.TODO()if needed). - Don’t store context in long-lived structs unless there is a documented compatibility reason.
- Context values are for request-scoped metadata, not optional argument transport.
- Honor cancellation and deadlines in I/O/concurrency paths.
- Never ignore returned errors in normal control flow.
- Avoid panic for expected failures.
- Keep error strings lowercase and punctuation-light.
- Use wrapping intentionally to define API behavior.
- Public APIs should have stable, documented behavior.
- Exported identifiers should have doc comments.
- Keep interfaces in consumer packages when possible.
- Prefer small, composable types and functions.
- Preserve backward compatibility unless explicitly changing major behavior.
- Every goroutine should have a clear stop condition.
- Avoid leaks via blocked sends/receives.
- Use context cancellation and channel closure patterns deliberately.
- Be explicit with ownership of shared mutable state.
Prefer semantic checks over string matching or direct equality on wrapped errors.
var ErrNotFound = errors.New("not found")
func lookup(id string) error {
if id == "" {
return fmt.Errorf("lookup %q: %w", id, ErrNotFound)
}
return nil
}
func handle(err error) bool {
return errors.Is(err, ErrNotFound)
}Useful for batch operations, cleanup failures, fan-out execution.
err := errors.Join(errA, errB, errC)
if errors.Is(err, errB) {
// true
}if pe, ok := errors.AsType[*os.PathError](err); ok {
_ = pe.Path
}- Use
%wwhen callers should be able to inspect causes. - Avoid wrapping internals when you do not want to expose implementation details.
Use cause-aware context APIs and inspect with context.Cause(ctx) where cancellation reasons matter.
- Use table-driven tests with
t.Runfor coverage and maintainability. - Test behavior and boundaries, not just happy paths.
- Keep tests deterministic and isolated.
- Unit coverage:
go test -cover ./...and-coverprofilewhen needed. - Integration coverage (Go 1.20+): build with
-cover, collect withGOCOVERDIR, analyze withgo tool covdata.
- Run
go test -race ./...for concurrency-sensitive changes.
- Use fuzz tests (
FuzzXxx) for parser/decoder/validation/string-processing boundaries. - Keep generated regression corpus under
testdata/fuzz/....
- Use
BenchmarkXxxand benchmark only stable scenarios. - Use
testing.B.Loopwhen appropriate (Go 1.24+).
- Run
go vet ./...for suspicious constructs.
go fmt ./...
go vet ./...
go test ./...
go test -race ./...
go test -cover ./...- CPU/heap/block profiling:
go test -cpuprofile/-memprofile+go tool pprof. - Runtime traces:
go test -trace+go tool trace. - Prefer measurement-driven optimization, not intuition-only changes.
- Use
go fix(Go 1.26 modernizers) when migrating codebases/toolchain idioms.
- Keep Go toolchain and dependencies up to date.
- Run vulnerability scanning routinely with
govulncheck ./.... - Treat external input as untrusted; validate at boundaries.
- For filesystem boundary constraints, consider
os.OpenRoot/os.Root(Go 1.24+) where applicable. - Use fuzzing and race detector as part of secure engineering baseline.
Before coding:
- Read
go.mod, key package docs, and existing tests. - Identify whether change affects public API, behavior contracts, or compatibility.
While coding:
- Keep deltas minimal and style-consistent.
- Add tests for new behavior and edge cases.
- Be explicit about error wrapping policy.
- Ensure context and goroutine lifecycle correctness.
Before finishing:
go fmt ./...go vet ./...go test ./...- Run
-racefor concurrency-related changes. - Run targeted benchmarks/profiling only when performance claims are made.
- Go release notes: https://go.dev/doc/devel/release
- Go 1.20: https://go.dev/doc/go1.20
- Go 1.21: https://go.dev/doc/go1.21
- Go 1.22: https://go.dev/doc/go1.22
- Go 1.23: https://go.dev/doc/go1.23
- Go 1.24: https://go.dev/doc/go1.24
- Go 1.25: https://go.dev/doc/go1.25
- Go 1.26: https://go.dev/doc/go1.26
- Modules: https://go.dev/doc/modules/managing-dependencies
- go.mod reference: https://go.dev/doc/modules/gomod-ref
errors: https://pkg.go.dev/errorscontext: https://pkg.go.dev/contexttesting: https://pkg.go.dev/testing- Race detector: https://go.dev/doc/articles/race_detector
- Fuzzing: https://go.dev/doc/security/fuzz/
- Coverage: https://go.dev/doc/build-cover
- Diagnostics: https://go.dev/doc/diagnostics
go vet: https://pkg.go.dev/cmd/vetgofmt: https://pkg.go.dev/cmd/gofmt- Vulnerability management: https://go.dev/doc/security/vuln/
govulncheck: https://go.dev/doc/tutorial/govulncheck- Doc comments guidance: https://go.dev/doc/comment
- Go review guidance: https://go.dev/wiki/CodeReviewComments