go-best-practices
Scannednpx machina-cli add skill lklimek/claudius/go-best-practices --openclawFiles (1)
SKILL.md
3.5 KB
Go Best Practices
Technical Standards
- Go Version: 1.21+ (or latest stable)
- Code Style: gofmt/goimports enforced
- Linting: golangci-lint with comprehensive checks
- Testing: go test with table-driven tests
- Documentation: One-line Godoc comment for every exported identifier; expand only when non-obvious
- Error Handling: Explicit with error wrapping (fmt.Errorf with %w)
- Modules: Go modules for dependency management
- Context: context.Context for cancellation and timeouts
Best Practices
- Accept interfaces, return structs
- Keep interfaces small (single-method often best)
- Use context.Context for cancellation propagation
- Always check errors — don't ignore with
_ - Use defer for cleanup (close files, unlock mutexes)
- Goroutines: always know when they exit
- Channels for communication, mutexes for state
- Prefer composition over embedding
- Use
internal/package for private code - Prefer standard library first
Common Patterns
- Error Wrapping:
fmt.Errorf("context: %w", err) - Options Pattern: Functional options for constructors
- Context: Pass as first parameter
- Interfaces: io.Reader, io.Writer, io.Closer patterns
- Middleware: Handler wrapping for HTTP servers
- Worker Pools: Channel-based task distribution
- Graceful Shutdown: Signal handling with context cancellation
Concurrency
- Always handle goroutine lifecycle — know when they exit
- Use context for cancellation propagation
- Protect shared state with mutexes or channels
- Use sync.WaitGroup to wait for goroutines
- Use buffered channels carefully — understand blocking
- Use select for channel multiplexing
- Implement worker pools for bounded concurrency
Error Handling
- Wrap errors with context:
fmt.Errorf("failed to read: %w", err) - Define custom error types for sentinel errors
- Use errors.Is() and errors.As() for checking
- Return errors as last return value
- Don't panic in library code — return errors
- Log errors at the right level in the call stack
Code Quality Tools
- Formatting: gofmt, goimports
- Linting: golangci-lint (staticcheck, errcheck, govet, etc.)
- Testing:
go test -race -cover ./... - Security: gosec
- Dependencies:
go mod tidy,go mod verify - Benchmarks:
go test -bench=. -benchmem
Common Pitfalls
- Don't ignore errors
- Don't use goroutines without understanding their lifecycle
- Don't use global variables excessively
- Don't use init() unless absolutely necessary
- Don't over-use interfaces early — add when needed
- Don't forget to close resources (files, connections)
- Don't use panic/recover for normal error handling
Code Review Checklist
- Idiomatic Go style (Effective Go compliance)
- Error handling: explicit checks, no ignored errors, proper wrapping with %w
- Goroutine lifecycle: clear start/stop, no leaks
- Interface design: small, focused, used appropriately
- Context propagation for cancellation
- Defer usage for cleanup
- DRY compliance: duplicated logic, copy-paste patterns
- Naming clarity: exported vs unexported, package naming
- Test quality: table-driven tests, meaningful assertions, race condition coverage
- Code brevity: flag code that can be expressed in fewer lines without losing clarity
Use GO-NNN prefix for all findings.
Source
git clone https://github.com/lklimek/claudius/blob/main/skills/go-best-practices/SKILL.mdView on GitHub Overview
Go Best Practices codifies standards used in writing, reviewing, and discussing Go code. It covers technical standards from versioning and style to testing patterns, error handling, and documentation, plus patterns for concurrency and code structure. The goal is to improve readability, reliability, and maintainability across Go projects.
How This Skill Works
This guide documents enforceable practices and common patterns that teams apply in code, reviews, and discussions. It highlights tools and patterns such as Go versioning, gofmt and golangci-lint, explicit error wrapping, context propagation, small interfaces, internal packages, and concurrency patterns like worker pools.
When to Use It
- GO-NNN: Use when starting a new Go service to align on standards across the team
- GO-NNN: Use during code reviews to check error handling, interfaces, and dependency design
- GO-NNN: Use when adding concurrency, goroutines, channels, and synchronization with lifecycle management
- GO-NNN: Use when writing tests, especially table-driven tests and coverage goals
- GO-NNN: Use when configuring CI/CD to enforce formatting, linting, module hygiene, and documentation
Quick Start
- Step 1: Initialize a module, run gofmt and goimports, and enable golangci-lint
- Step 2: Add explicit error wrapping and a context aware API, then write a table-driven test
- Step 3: Run tests with race and cover, and review against the code review checklist
Best Practices
- GO-NNN: Accept interfaces and return concrete structs to improve clarity and testability
- GO-NNN: Keep interfaces small and focused to reduce coupling
- GO-NNN: Use context.Context for cancellation and deadlines across API boundaries
- GO-NNN: Always check errors and avoid ignoring them with blank identifiers
- GO-NNN: Use defer for cleanup and manage goroutine lifecycles with WaitGroups
Example Use Cases
- GO-NNN: Designing a function that returns an interface while hiding the implementation behind a concrete type
- GO-NNN: Implementing the options pattern for constructors to compose behavior
- GO-NNN: Propagating context through HTTP handlers and business logic to allow cancellation
- GO-NNN: Wrapping errors with contextual messages and using errors.Is / errors.As for checks
- GO-NNN: Building a worker pool with channels and a WaitGroup to cap concurrency safely
Frequently Asked Questions
Add this skill to your agents