4.4 KiB
4.4 KiB
agents.md
Code Style
- Follow standard Go conventions:
gofmt,goimports, andgolangci-lint. - Keep packages small and focused. Name them short, lowercase, no underscores.
- Avoid unnecessary abstractions — prefer simple, readable code over clever code.
- Define interfaces at the point of use, not the point of implementation. Keep them small.
Error Handling
- Always handle errors explicitly — never ignore them with
_. - Wrap errors with context:
fmt.Errorf("doing X: %w", err). - Use
errors.Is/errors.Asfor matching, not string comparison. - Reserve
panicfor unrecoverable programmer mistakes, not runtime errors.
Concurrency
- Pass
context.Contextas the first argument to any blocking or I/O function. - Never store a
Contextin a struct. Never usecontext.Background()deep in business logic. - Always manage goroutine lifecycles — use
errgroup,sync.WaitGroup, or channels. - Protect shared state with mutexes or by confining it to a single goroutine.
Testing
- Write table-driven tests using
t.Runfor clarity and coverage. - Use the standard
testingpackage. Reach fortestifyonly when it genuinely reduces noise. - Prefer real implementations over mocks where feasible (e.g.,
httptest, in-memory stores). - Keep tests close to the code they test; use
_testpackages for black-box testing. - Benchmark with
testing.Bbefore optimizing anything.
Dependencies & Modules
- Keep
go.modtidy — rungo mod tidybefore committing. - Minimize external dependencies; prefer the standard library.
- Pin versions explicitly and review dependency updates carefully.
General
- Measure before optimizing. Use
pproffor profiling. - Log at boundaries (entry/exit of services), not inside every function.
- Prefer explicit over implicit — avoid
init()and global state.
API Design
- Propagate
context.Contextthrough every layer of an API — from handler to store. - Never drop context mid-call or substitute it with
context.Background()silently. - Honor context cancellation and deadlines in all I/O and long-running operations.
- Design APIs so callers can always pass a context; if a function does I/O, it takes a
ctx.
Documentation
- Document every exported type, function, method, and constant — no exceptions.
- Follow Go doc conventions: start the comment with the name of the thing being documented.
- Package-level comments should explain purpose and usage, not implementation details.
- Include examples (
Example*functions) for non-trivial exported APIs.
// UserStore retrieves and persists user records.
type UserStore interface { ... }
// GetByID returns the user with the given ID, or ErrNotFound if absent.
func (s *store) GetByID(ctx context.Context, id string) (*User, error) { ... }
Testing (expanded)
- Write tests as you write code — not after, not when asked. Tests are not optional.
- Every exported function and critical internal path must have at least one test.
- Cover edge cases, error paths, and boundary conditions — not just the happy path.
- Use
t.Helper()in shared test utilities to keep failure output pointing at the call site. - Integration tests live in
test/or behind a build tag (e.g.,//go:build integration).
Microservice Readiness
- Expose
/healthz(liveness) and/readyz(readiness) endpoints on a dedicated port. - Liveness indicates the process is alive; readiness indicates it can serve traffic.
- Handle
SIGTERMandSIGINTwith graceful shutdown: stop accepting new requests, finish in-flight work, release resources, then exit. - Set explicit timeouts on
http.Server:ReadTimeout,WriteTimeout,IdleTimeout. - Use
errgroupwith a context to coordinate shutdown across goroutines cleanly.
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGTERM, syscall.SIGINT)
defer stop()
Security
- Never log secrets, tokens, passwords, or PII — scrub them before logging.
- Validate and sanitize all external input; never trust data from outside the process boundary.
- Use
crypto/randfor all randomness that touches security; nevermath/rand. - Enforce TLS for all external communication; keep cipher suites and TLS version current.
- Follow the principle of least privilege for service accounts, DB roles, and IAM policies.
- Scan dependencies for known CVEs regularly (e.g.,
govulncheck). - Set strict timeouts on all outbound HTTP clients — never use the default zero-timeout client.