In Go, a failure is represented by an error value returned as an ordinary result, rather than handled through try/catch. The value can be compared, returned, wrapped with context, logged, or propagated. section 7.0 section 7.8
Avoid these common mistakes when handling failures:
- Do not compare a possibly wrapped error directly with a sentinel using ==; use errors.Is instead. section 7.4 section 7.8
- Do not silently discard an error from a deferred operation. Handle it, propagate it, or ignore it explicitly with the blank identifier. section 7.7 section 7.8
- Log or return an error according to the context; logging already counts as handling it. section 7.8
Checking an expected failure
A query may return sql.ErrNoRows when no rows are found. Because this expected condition is a sentinel error, compare it with errors.Is(err, sql.ErrNoRows), especially when another function may have wrapped it with additional context. section 7.4 section 7.8
const query = "..."
func getBalance(db *sql.DB, clientID string) (
float32, error) {
rows, err := db.Query(query, clientID)
if err != nil {
return 0, err
}
defer rows.Close() #1
// Use rows
}
Inspect the deferred database-row cleanup example, then compare explicit ignoring, logging, and propagation of the Close error. section 7.7











