Loading...
Loading...
Comprehensive guide for Go database access. Covers parameterized queries, struct scanning, NULLable column handling, error patterns, transactions, isolation levels, SELECT FOR UPDATE, connection pool, batch processing, context propagation, and migration tooling. Use this skill whenever writing, reviewing, or debugging Golang code that interacts with PostgreSQL, MariaDB, MySQL, or SQLite. Also triggers for database testing or any question about database/sql, sqlx, pgx, or SQL queries in Golang. This skill explicitly does NOT generate database schemas or migration SQL.
npx skill4agent add samber/cc-skills-golang golang-databaserows.Close()Community default. A company skill that explicitly supersedesskill takes precedence.samber/cc-skills-golang@golang-database
database/sqlsqlxpgx*ContextQueryContextExecContextGetContextsql.ErrNoRowserrors.Isdefer rows.Close()QueryContextdb.QueryQuery*Rowsdb.ExecBeginTxxCommitSELECT ... FOR UPDATE*string*intsql.NullXxxSetMaxOpenConnsSetMaxIdleConnsSetConnMaxLifetimeSetConnMaxIdleTime| Library | Best for | Struct scanning | PostgreSQL-specific |
|---|---|---|---|
| Portability, minimal deps | Manual | No |
| Multi-database projects | | No |
| PostgreSQL (30-50% faster) | | Yes (COPY, LISTEN, arrays) |
| GORM/ent | Avoid | Magic | Abstracted away |
// ✗ VERY BAD — SQL injection vulnerability
query := fmt.Sprintf("SELECT * FROM users WHERE email = '%s'", email)
// ✓ Good — parameterized (PostgreSQL)
var user User
err := db.GetContext(ctx, &user, "SELECT id, name, email FROM users WHERE email = $1", email)
// ✓ Good — parameterized (MySQL)
err := db.GetContext(ctx, &user, "SELECT id, name, email FROM users WHERE email = ?", email)query, args, err := sqlx.In("SELECT * FROM users WHERE id IN (?)", ids)
if err != nil {
return fmt.Errorf("building IN clause: %w", err)
}
query = db.Rebind(query) // adjust placeholders for your driver
err = db.SelectContext(ctx, &users, query, args...)allowed := map[string]bool{"name": true, "email": true, "created_at": true}
if !allowed[sortCol] {
return fmt.Errorf("invalid sort column: %s", sortCol)
}
query := fmt.Sprintf("SELECT id, name, email FROM users ORDER BY %s", sortCol)samber/cc-skills-golang@golang-securitydb:"column_name"pgx.CollectRowspgx.RowToStructByName*string*time.Timefunc GetUser(id string) (*User, error) {
var user User
err := db.GetContext(ctx, &user, "SELECT id, name FROM users WHERE id = $1", id)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, ErrUserNotFound // translate to domain error
}
return nil, fmt.Errorf("querying user %s: %w", id, err)
}
return &user, nil
}func GetUser(id string) (u *User, exists bool, err error) {
var user User
err := db.GetContext(ctx, &user, "SELECT id, name FROM users WHERE id = $1", id)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, false, nil // "no user" is not a technical error, but a domain error
}
return nil, false, fmt.Errorf("querying user %s: %w", id, err)
}
return &user, true, nil
}rows, err := db.QueryContext(ctx, "SELECT id, name FROM users")
if err != nil {
return fmt.Errorf("querying users: %w", err)
}
defer rows.Close() // prevents connection leaks
for rows.Next() {
// ...
}
if err := rows.Err(); err != nil { // always check after iteration
return fmt.Errorf("iterating users: %w", err)
}| Error | How to detect | Action |
|---|---|---|
| Row not found | | Return domain error |
| Unique constraint | Check driver-specific error code | Return conflict error |
| Connection refused | | Fail fast, log, retry with backoff |
| Serialization failure | PostgreSQL error code | Retry the entire transaction |
| Context canceled | | Stop processing, propagate |
*Context// ✗ Bad — no context, query runs until completion even if client disconnects
db.Query("SELECT ...")
// ✓ Good — respects context cancellation and timeouts
db.QueryContext(ctx, "SELECT ...")samber/cc-skills-golang@golang-contextSELECT FOR UPDATEdb.SetMaxOpenConns(25) // limit total connections
db.SetMaxIdleConns(10) // keep warm connections ready
db.SetConnMaxLifetime(5 * time.Minute) // recycle stale connections
db.SetConnMaxIdleTime(1 * time.Minute) // close idle connections fasterSELECT FOR UPDATEsamber/cc-skills-golang@golang-securitysamber/cc-skills-golang@golang-contextsamber/cc-skills-golang@golang-error-handlingsamber/cc-skills-golang@golang-testing