liveBook · Manning

Database/sql

As explained in Go by Example

database/sql is Go's standard library package that provides a database-independent API for working with SQL databases.

database/sql is Go’s uniform API for working with SQL and other row-oriented databases. Application code uses it rather than a database-specific driver API: a driver is registered under a name, then sql.Open returns a *sql.DB handle for executing queries and receiving results. The same pattern can target SQLite or PostgreSQL, while driver packages perform the database-specific work. section 10.1 section 10.1.1

Figure 10.1 The sql package abstracts underlying databases with drivers. The sql package’s registry stores registered drivers, and *DB manages a connection pool.
A computer screen shot of a computer

AI-generated content may be incorrect.

Follow the separation of responsibilities: application code calls database/sql, the package selects a registered driver, and the driver communicates with the chosen database. section 10.1

A *sql.DB is not a single database connection. It is a concrete handle that manages a connection pool, selecting, opening, reusing, and closing connections as operations require. Keeping one *sql.DB for the program lifetime avoids reconnecting for every query; the pool can also retry some failures automatically. section 10.1 section 10.1.2

Connect through database/sql in a small, explicit sequence:

  • Choose and download a driver module. The standard library supplies the abstraction but does not bundle SQL drivers. section 10.1.1
  • Register the driver, commonly with a blank import, so its initialization makes the driver available to database/sql. section 10.1.1
  • Call sql.Open with the registered driver name and a driver-specific data source name (DSN). Open checks the driver registry and returns *sql.DB. section 10.1
  • Use DB.PingContext to verify that the selected driver can connect before proceeding with database work. section 10.1.2

Isolate SQLite behind a package entry point

A sqlite package can blank-import modernc.org/sqlite and expose a Dial function. Dial calls sql.Open("sqlite", dsn), wraps an opening error, then calls PingContext and wraps a connectivity error. This keeps SQLite-specific imports and connection details in one place instead of scattering them through the application. SQL can remain compatible with PostgreSQL so that a PostgreSQL driver can be substituted later. section 10.1.1 section 10.1.2

Listing 10.2 Dialing the database (link/sqlite/sqlite.go)
package sqlite

import (
    "context"
    "database/sql"
    "fmt"
    _ "modernc.org/sqlite"
)

// Dial connects to SQLite and applies the schema for convenience.
func Dial(ctx context.Context, dsn string) (*sql.DB, error) {
    db, err := sql.Open("sqlite", dsn) #1
    if err != nil {
        return nil, fmt.Errorf("opening: %w", err)
    }
    if err := db.PingContext(ctx); err != nil { #2
        return nil, fmt.Errorf("pinging: %w", err)
    }
    return db, nil
}

Inspect a complete Dial helper that opens a SQLite-backed *sql.DB and verifies connectivity with a context-aware ping. section 10.1.2

Tune pooling only from observed workload behavior. SetMaxOpenConns and SetMaxIdleConns limit active and idle connections; SetConnMaxLifetime and SetConnMaxIdleTime limit reuse duration. Excessively high limits waste resources, while low limits can cause connection churn, so benchmark and test instead of guessing. section 10.1.2

Driver choice affects deployment. A pure-Go SQLite driver avoids CGO, which otherwise adds C bindings, external dependencies, slower builds, and cross-compilation complexity. A CGO-based driver may offer performance or features, but its benefits should justify that overhead. section 10.1.1

How Go by Example covers it

How deep it goes
Explains driver registration, *sql.DB pooling, connectivity checks, and pool-tuning trade-offs without implementing a driver.
Examples
Uses SQLite and PostgreSQL Open calls plus a Dial helper using modernc.org/sqlite and PingContext.
What you can do after
Operate/configure it by registering a driver, opening and verifying *sql.DB, and tuning its connection pool.
How it connects
Connects SQL drivers, connection pools, DSNs, CGO, integration testing, and consumer-driven interfaces.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Go by Example. The section links point to the parts of the book it draws on.