A Close method terminates or releases an associated resource and returns an error describing whether cleanup succeeded. A common mistake is writing defer rows.Close() and silently discarding that result. Cleanup can fail while releasing a database connection or flushing buffered file data, so the correct response depends on whether that failure matters. section 7.7 section 10.5.3
type Closer interface {
Close() error
}
The Closer interface captures the essential API shape: Close performs cleanup and reports an error. section 7.7
Choose the cleanup pattern according to the consequence of a failed Close:
- Explicitly ignore an unimportant error with defer func() { _ = rows.Close() }(). This documents the decision instead of hiding an unchecked return value. section 7.7
- Log cleanup failures when they matter operationally but should not replace the function's primary result. section 7.7 section 10.5.3
- Propagate the Close error when cleanup can reveal a failed operation, especially after writing a file. Use a named result and replace the prior error only when no earlier error exists. section 7.7 section 10.5.3
- Call Sync before Close when durability on disk is required; after successful synchronization, a Close error may be safely ignored in the shown pattern. section 10.5.3
Preserving a write or close failure
A deferred close can update a named result without masking an earlier write error: func writeToFile(filename string, content []byte) (err error) { // Open file defer func() { closeErr := f.Close() if err == nil { err = closeErr } }() _, err = f.Write(content) return } If Write succeeds but buffered output fails during Close, the caller receives that cleanup error. If Write already failed, the original error remains visible. section 10.5.3
Resources that implement io.Closer should eventually be closed, but the right timing and error policy come from the API contract. Explicit cleanup also avoids waiting for garbage collection and exposes failures sooner. section 10.5.3



