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

使用GORM无法捕获ErrRecordNotFound错误,无法执行创建操作

问题解决:GORM未捕获ErrRecordNotFound导致程序终止

问题代码

err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where("description = ?", item.Description).First(&exist).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
    err = r.db.Create(&entity.Item{
        Name:        item.Name,
        Description: item.Description,
        Quantity:    item.Quantity,
        OrderID:     order.ID,
    }).Error
    if err != nil {
        return err
    }
}

日志信息

record not found
[5.093ms] [rows:0] SELECT * FROM "items" WHERE description = 'iPhone' ORDER BY "items"."id" LIMIT 1 FOR UPDATE

问题分析

程序直接终止且未执行创建逻辑,核心原因有两个:

  1. 未处理ErrRecordNotFound之外的其他错误,若查询时出现数据库连接、权限等异常,代码会跳过分支直接执行后续逻辑,引发未捕获错误导致程序终止。
  2. 查询用事务实例tx,但创建用非事务实例r.db,跨事务操作可能引发上下文异常。
  3. 部分GORM版本中,errors.Is可能无法正确匹配包装后的ErrRecordNotFound错误。

修复方案

修复后代码

err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where("description = ?", item.Description).First(&exist).Error
if err != nil {
    // 优先判断记录不存在的情况,支持直接比较或errors.Is
    if err == gorm.ErrRecordNotFound || errors.Is(err, gorm.ErrRecordNotFound) {
        // 使用事务实例执行创建,保持事务一致性
        err = tx.Create(&entity.Item{
            Name:        item.Name,
            Description: item.Description,
            Quantity:    item.Quantity,
            OrderID:     order.ID,
        }).Error
        if err != nil {
            return err
        }
    } else {
        // 直接返回其他查询错误,避免程序异常终止
        return err
    }
}
// 此处可添加查询到记录后的处理逻辑

关键修复点

  • 增加全局错误判断:先捕获所有查询错误,再分支处理不同类型,避免遗漏异常。
  • 统一事务上下文:创建操作改用tx.Create,确保所有操作在同一个事务中执行。
  • 兼容错误匹配:同时支持直接比较和errors.Is,适配不同GORM版本的错误包装逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 05:42:13