liveBook · Manning

Sql.Rows

As explained in 100 Go Mistakes and How to Avoid Them

sql.Rows is a database/sql type that represents the result rows returned by a query.

A common mistake is treating rows.Close() as harmless cleanup. sql.Rows represents query results and implements a closer; omitting closure can leak a database connection and prevent its return to the pool. A plain defer rows.Close() also discards any closure error. section 10.5.2 section 7.7

Closing query results

After a successful query, defer closure before using the rows: rows, err := db.Query(query, clientID) if err != nil { return 0, err } defer func() { if err := rows.Close(); err != nil { log.Printf("failed to close rows: %v", err) } }() // Use rows This logs a failure to release the connection instead of silently ignoring it. If closure errors must reach the caller, use named result parameters and assign the deferred error carefully, while preserving an earlier query or scan error. section 10.5.2 section 7.7

Choose the cleanup policy according to the importance of the closure error:

  • Use defer rows.Close() only when intentionally accepting the ignored error. section 7.7
  • Use a deferred function with logging when failed release should be observable. section 7.7 section 10.5.2
  • Use named result parameters when the deferred closure error must be propagated; avoid replacing an existing operation error. section 7.7
// Open connection
 
rows, err := db.Query("SELECT * FROM CUSTOMERS")     #1
if err != nil {
    return err
}
 
defer func() {                                       #2
    if err := rows.Close(); err != nil {
        log.Printf("failed to close rows: %v\n", err)
    }
}()
 
// Use rows

Shows the normal placement of deferred rows.Close immediately after a successful Query call. section 10.5.2

How 100 Go Mistakes and How to Avoid Them covers it

How deep it goes
Explains result ownership, deferred cleanup, ignored errors, logging, and named-result propagation without detailing SQL row parsing.
Examples
Demonstrates Query results, deferred Close, explicit error ignoring, logging, and named-return error propagation.
What it assumes
Assumes familiarity with Go errors, defer, named results, database queries, and connection pools.
What you can do after
Operate database/sql queries without leaking connections and choose whether Close errors are ignored, logged, or propagated.
How it connects
Connects sql.Rows with database/sql queries, io.Closer, defer, error handling, and connection pools.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 Go Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.