Database Access

database/sql, connection pools, queries, transactions, and sqlx.

Intermediate 35 min read 🐹 Go

database/sql

Go's database/sql package provides a generic interface for SQL databases. It handles connection pooling, prepared statements, and transactions. You pair it with a driver for your specific database.

go get github.com/lib/pq          # PostgreSQL
go get github.com/go-sql-driver/mysql  # MySQL
go get modernc.org/sqlite          # SQLite (pure Go)
import (
    "database/sql"
    _ "github.com/lib/pq"
)

db, err := sql.Open("postgres", "postgres://user:pass@localhost/mydb?sslmode=disable")
if err != nil {
    log.Fatal(err)
}
defer db.Close()

// Verify connection
if err := db.Ping(); err != nil {
    log.Fatal(err)
}

Queries

// Single row
var name string
var age int
err := db.QueryRow("SELECT name, age FROM users WHERE id = $1", 42).Scan(&name, &age)

// Multiple rows
rows, err := db.Query("SELECT name, age FROM users WHERE age > $1", 18)
if err != nil { log.Fatal(err) }
defer rows.Close()

for rows.Next() {
    var name string
    var age int
    if err := rows.Scan(&name, &age); err != nil { log.Fatal(err) }
    fmt.Printf("%s: %d\n", name, age)
}

// Insert/Update/Delete
result, err := db.Exec("INSERT INTO users (name, age) VALUES ($1, $2)", "Alice", 30)
id, _ := result.LastInsertId()
affected, _ := result.RowsAffected()

⚠️ Always use parameterized queries

Never build SQL with string concatenation: fmt.Sprintf("WHERE name = '%s'", name) is vulnerable to SQL injection. Always use $1 (Postgres) or ? (MySQL) placeholders.

Key Takeaway: Always defer rows.Close(). Always use parameterized queries. Use db.Ping() to verify connectivity. The connection pool is managed automatically by database/sql.

Practice Exercises

Medium Build a Mini Project

Combine concepts from this tutorial to build a small utility or tool.

Medium Debug Challenge

Introduce a bug in one of the code examples and practice finding and fixing it.

Hard Refactoring Exercise

Rewrite one example using a different approach and compare the tradeoffs.