Stage 3 · Build
Databases & Persistence
database/sql
Use sql.DB, QueryContext, ExecContext, prepared statements, scanning rows, and nullable columns.
sql.DB Connection
sql.DB is a pool of connections, not a single connection. You never open or close individual connections. The pool handles connection reuse, health checks, and retry logic. Configure pool size to match your database capacity.
Querying Rows
Use QueryContext for SELECT queries that return multiple rows. Always defer rows.Close() to release the connection back to the pool. Iterate with rows.Next() and scan results into variables.
Executing Commands
Use ExecContext for INSERT, UPDATE, and DELETE statements. It returns a Result object with the number of rows affected and the last insert ID.
Prepared Statements
Prepared statements parse the SQL once and execute it multiple times with different parameters. They improve performance for repeated queries and prevent SQL injection.
Scanning Rows
Scan maps column values to Go variables. The types must match: VARCHAR to string, INT to int, DECIMAL to float64 or decimal.Decimal, TIMESTAMP to time.Time. Mismatches cause runtime errors.
Nullable Columns
Database columns can be NULL. Go zero values do not distinguish between NULL and empty string. Use sql.NullString, sql.NullInt64, sql.NullTime for nullable columns.
Instead of checking NullString in Go, use COALESCE in SQL: SELECT COALESCE(bio, '') FROM users. This returns empty string for NULL, letting you scan directly into a string.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.