You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用defer关闭sql.Rows是否有风险?我的优化方案是否合理?

你的修改方案存在不足,推荐补充nil校验逻辑

你遇到的defer rows.Close()触发panic的核心原因,大概率是传入getResultString的rows参数为nil——当db.Query执行失败返回错误时,rows通常会是nil,直接调用nil指针的Close()方法必然触发panic。

你的当前修改仅对rows.Close()的错误做了捕获打印,但没有处理rows本身为nil的情况,如果调用方传入nil,依然会触发panic,所以这不是完整的推荐做法。

推荐的正确实现方式

需要在defer的匿名函数中先判断rows是否为nil,再执行关闭操作,同时建议使用日志库替代fmt.Println来记录错误(便于线上排查):

import "log"

func getResultString(rows *sql.Rows) (*string, error) {
    defer func() {
        if rows != nil { // 先判断rows非nil再执行关闭
            if err := rows.Close(); err != nil {
                log.Printf("Failed to close rows: %v", err)
            }
        }
    }()

    var result string
    if rows.Next() {
        if err := rows.Scan(&result); err != nil {
            return nil, fmt.Errorf("scan err: %v", err)
        }
        return &result, nil
    }
    return nil, fmt.Errorf("query err: %v", rows.Err())
}

额外优化建议

  1. 参数前置校验:可以在函数开头就校验rows是否为nil,提前返回错误,避免后续无效逻辑执行:
func getResultString(rows *sql.Rows) (*string, error) {
    if rows == nil {
        return nil, fmt.Errorf("invalid nil rows parameter")
    }
    // 后续defer和业务逻辑...
}
  1. 错误处理标准化:统一使用log或项目内的日志组件记录Close错误,不要用fmt.Println(线上环境无法留存日志,不利于问题排查)。

内容的提问来源于stack exchange,提问作者sclee1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 21:39:57