在 go 中使用 `database/sql` 包执行查询时,手动调用 `rows.close()` 容易遗漏,导致连接泄漏;推荐使用 `defer rows.close()` 确保资源及时释放,兼顾安全性与代码可读性。
Go 的 defer 语句是专为这类资源清理场景设计的语言特性——它能保证函数返回前(无论是否发生 panic、是否多路返回)自动执行指定操作。相比传统“先 open、后 close”的显式配对写法,defer 将清理逻辑紧邻资源获取处声明,大幅提升代码健壮性与可维护性。
以下是一个典型优化示例:
rows, err := db.Query("SELECT id, name FROM users WHERE active = $1", true)
if err != nil {
log.Fatal(err)
}
defer rows.Close() // ✅ 清晰、可靠:紧贴 Query 调用,且必定执行
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,不影响 defer 执行
}
// 处理单行数据...
}
// rows.Close() 在此处自动触发(函数返回前)⚠️ 注意事项:
✅ 总结:将 defer rows.Close() 作为查询后的第一行(紧随 Query/QueryRow 调用之后),是最符合 Go 惯例、最不易出错的资源管理实践。它既消除了遗忘关闭的风险,又让资源生命周期一目了然,是编写生产级数据库操作代码的必备习惯。