2.6 KiB
2.6 KiB
Contract: Go Code Style and Project Conventions
Version: 1.0
Logging
See kit/patterns/go-logging/contract.md for full rules.
Summary: use slog, log to stdout/stderr (binary console), never to browser console.
Error Handling
Always wrap errors with context. Use fmt.Errorf("...: %w", err).
// CORRECT
if err := db.Save(&record).Error; err != nil {
return fmt.Errorf("save component %s: %w", record.ID, err)
}
// WRONG — loses context
return err
- Never silently discard errors with
_in production paths. - Return errors up the call stack; log at the handler/task boundary, not deep in service code.
Code Formatting
- Always run
gofmtbefore committing. No exceptions. - No manual alignment of struct fields or variable assignments.
HTTP Handler Structure
Handlers are thin. Business logic belongs in a service layer.
Handler → validates input, calls service, writes response
Service → business logic, calls repository
Repository → SQL queries only, returns domain types
- Handlers must not contain SQL queries.
- Services must not write HTTP responses.
- Repositories must not contain business rules.
Startup Sequence (Go web app)
1. Parse flags / load config
2. Connect to DB — fail fast if unavailable (see go-database contract)
3. Run migrations
4. Initialize services and background workers
5. Register routes
6. Start HTTP server
Never reverse steps 2 and 5. Never start serving before migrations complete.
Configuration
- Config lives in a single
config.yamlfile, not scattered env vars. - Env vars may override config values but must be documented.
- Never hardcode ports, DSNs, or file paths in application code.
- Provide a
config.example.yamlcommitted to the repo. - The actual
config.yamlis gitignored.
Template / UI Rendering
- Server-rendered HTML via Go templates is the default.
- htmx for partial updates — no full SPA framework unless explicitly decided.
- Template errors must return
500and log the error server-side. - Never expose raw Go error messages to the end user in rendered HTML.
Business Logic Placement
- Threshold computation, status derivation, and scoring live on the server.
- The UI only reflects what the server returns — it does not recompute status client-side.
- Example: "critical / warning / ok" badge color is determined by the handler, not by JS.
Dependency Rules
- Prefer standard library. Add a dependency only when the stdlib alternative is significantly worse.
- Document the reason for each non-stdlib dependency in a comment or ADL entry.