Golang Database
Priority: P0 (CRITICAL)
Principles
- Prefer Raw SQL/Builders over ORMs:
sqlcgenerates type-safe Go from SQL. ORMs (GORM) can obscure performance. - Repository Pattern: Abstract DB access behind interfaces in
internal/port/. - Connection Pooling: Always configure pool settings.
- Transactions: ACID logic must use transactions. Pass
context.Contexteverywhere.
Implementation Workflow
- Choose driver — PostgreSQL:
pgx/v5; MySQL:go-sql-driver/mysql; SQLite:modernc.org/sqlite. - Configure pool — Set
MaxOpenConns,MaxIdleConns, andConnMaxLifetimeon the connection. - Define repository interface — Abstract DB access behind an interface at the consumer side.
- Use context-aware queries — Always use
QueryContext/ExecContext; bare queries ignore timeouts. - Close rows — Always
defer rows.Close()and checkrows.Err()after iteration. - Wrap in transactions — Use transactions for multi-step operations requiring atomicity.
See repository pattern and connection pool examples
Anti-Patterns
- ❌ Global
var db *sql.DB— inject DB connection via constructor - ❌ Bare
Query()/Exec()without context — useQueryContext/ExecContext - ❌ Leaked rows — always
defer rows.Close()and checkrows.Err()