644 字
3 分钟
错误处理与调试

GORM 错误处理与调试#

Traditional API#

每次操作都检查返回的 Error:

result := db.Where("email = ?", email).First(&user)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return ErrUserNotFound
}
return fmt.Errorf("find user: %w", result.Error)
}

不要只判断 RowsAffected,也不要忽略 result.Error。

Generics API#

Generics API 将错误直接返回:

user, err := gorm.G[User](db).Where("id = ?", id).First(ctx)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return ErrUserNotFound
}
return fmt.Errorf("find user: %w", err)
}

统一使用 errors.Is 判断 GORM 和驱动错误,保留 %w 链路,不要只比较错误字符串。

TranslateError#

db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
TranslateError: true,
})

开启后,部分数据库错误会转换为 GORM 通用错误,例如记录不存在、重复键或外键约束错误。转换可以简化跨数据库判断,但排查问题时仍应记录原始错误上下文。

日志级别#

db.Debug().Where("id = ?", id).First(&user)

常用级别:

  • Silent:不输出 SQL。
  • Error:只输出错误。
  • Warn:输出错误和慢 SQL,通常适合生产默认值。
  • Info:输出全部 SQL,适合本地调试或短时间排查。

生产日志建议包含请求 ID、业务操作、耗时、RowsAffected 和错误分类,而不是只打印 SQL 字符串。

记录 SQL 但保护敏感数据#

logger.Config{
ParameterizedQueries: true,
IgnoreRecordNotFoundError: true,
SlowThreshold: 200 * time.Millisecond,
}

密码、Token、身份证号等敏感字段不要进入 SQL 日志、错误响应或调试输出。开发阶段打印参数也要确认日志不会被上传到公共系统。

DryRun 与执行计划#

stmt := db.Session(&gorm.Session{DryRun: true}).
Where("email = ?", email).
First(&User{}).Statement
fmt.Println(stmt.SQL.String())
fmt.Println(stmt.Vars)

拿到 SQL 后,在目标数据库中使用 EXPLAIN 检查索引、扫描行数、排序和连接方式。DryRun 不能替代数据库执行计划。

常见错误定位#

现象先检查
record not found是否应该把它映射为 404/业务未找到,而不是 500
invalid field found关联字段、外键、引用字段和标签
无条件更新/删除被拒绝是否漏写 Where,不要直接全局开启放行
唯一键冲突业务幂等键、并发竞态和数据库唯一索引
连接超时DSN、网络、连接池、数据库负载和上下文超时
SQL 慢生成 SQL、参数、索引、数据量和执行计划

Repository 边界#

Repository 可以把底层错误转成领域错误:

var ErrUserNotFound = errors.New("user not found")
func FindUser(ctx context.Context, db *gorm.DB, id uint) (User, error) {
var user User
if err := db.WithContext(ctx).First(&user, id).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return User{}, ErrUserNotFound
}
return User{}, fmt.Errorf("find user %d: %w", id, err)
}
return user, nil
}

Handler 不需要知道具体数据库错误;Service 负责业务语义,Repository 负责持久化细节。

官方资料#

错误处理与调试
https://shirone.mysqil.com/posts/gorm/错误处理与调试/
作者
HikariTish
发布于
2026-07-30
许可协议
CC BY-NC-SA 4.0

分享文章

生成精美分享图或复制链接,与更多人分享本文。

继续阅读

沿着主题读

基于共同的标签与分类

换条路线

从其他文章中稳定抽取