使用 `defer rows.close()` 可以确保查询结果集在函数返回前自动关闭,避免因遗漏调用导致连接泄漏,是 go 中推荐的标准实践。
在 Go 的数据库操作中,*sql.Rows 对象代表一个查询结果集,它底层持有一个数据库连接(或连接池中的会话)。虽然 rows.Close() 并不直接关闭物理连接(连接通常由连接池复用),但必须显式调用它——否则该结果集会持续占用连接资源,阻碍连接归还给池,最终可能导致 too many connections 或 i/o timeout 等错误。
最简洁、安全且符合 Go 习惯的写法是结合 defer:
rows, err := db.Query("SELECT id, name FROM users WHERE active = $1", true)
if err != nil {
log.Fatal(err)
}
defer rows.Close() // ✅ 在函数退出时自动执行,无论是否发生 panic 或提前 return
for rows.Next() {
var id int
var name string
if err := rows.Scan(&id, &name); err != nil {
log.Printf("scan error: %v", err)
continue // 或 break,视业
务逻辑而定
}
fmt.Printf("User %d: %s\n", id, name)
}
// 注意:此处无需再手动调用 rows.Close()✅ 优势说明:
⚠️ 注意事项:
总结:defer rows.Close() 不仅是更短的写法,更是 Go “明确资源生命周期”设计哲学的体现——让清理逻辑紧贴资源获取,兼顾安全、简洁与可维护性。