Files
bible/kit/patterns/go-code-style/contract.md
Michael Chus 40d1c303bb Add shared engineering rule contracts
- go-logging: slog, server-side only, structured attributes
- go-database: MySQL cursor safety, soft delete, GORM tags, fail-fast, N+1 prevention
- go-background-tasks: Task Manager pattern, polling, no SSE
- go-code-style: layering, error wrapping, startup sequence, config, templating
- import-export: CSV Excel-compatible rules (BOM, semicolon, decimal comma, DD.MM.YYYY)
- table-management: filtering and pagination rules added
- CLAUDE.template.md: updated to reference all shared contracts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 16:39:39 +03:00

2.5 KiB

Contract: Go Code Style and Project Conventions

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 gofmt before 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.yaml file, 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.yaml committed to the repo.
  • The actual config.yaml is 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 500 and 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.