SQLite provides embedded relational storage for applications that need persistence without installing or operating a separate database server. A local database file keeps link records available after an HTTP server restarts, while the same design concepts apply to other SQL databases through Go’s database/sql package. section 10.0
A practical Go integration follows this sequence:
- Call sql.Open with a SQLite data source name; it verifies the registered driver and returns a database handle with an initially empty pool. section 10.1.2
- Call DB.PingContext to establish the first connection and confirm that SQLite is reachable. section 10.1.2
- Keep the *sql.DB handle for the application lifetime so queries can reuse its connection pool instead of reconnecting for every operation. section 10.1.2
- Apply a schema through a database query before inserting or reading records, then place the database-backed service behind interfaces used by HTTP handlers. section 10.0
Persisting links across restarts
A link server can accept a database DSN such as file:links.db?mode=rwc, call sqlite.Dial, construct sqlite.NewShortener, and pass the resulting service to its HTTP handlers. Running the server, shortening a URL, restarting the process, and resolving the returned key demonstrates persistence in the links.db file. section 10.4.3
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 function that imports the SQLite driver, opens the database, pings it with a context, and wraps connection errors. section 10.1.2














