如何让 GORM 打印 SQL 语句?三种方式全解析

前言

在使用 GORM 开发 Go 项目时,经常需要查看实际执行的 SQL 语句------排查慢查询、调试数据逻辑、确认查询条件是否正确......但 GORM 默认是关闭的,不会主动把 SQL 打印出来。


方式一:全局开启 Debug 模式(最简单)

GORM 提供了一个非常方便的方法------db.Debug(),它会把所有 SQL 语句打印到标准输出,包括执行的 SQL、影响的行数和耗时。

只需一行代码:

go 复制代码
db = db.Debug()

之后所有的查询都会打印 SQL,例如:

复制代码
[0.23ms] [rows:1] SELECT * FROM `users` WHERE `id` = 1

适合场景: 开发环境整体调试,想看全局 SQL 的情况。

实际项目中怎么做? 通常会用一个环境变量来控制。初始化数据库连接时:

go 复制代码
func InitDB() {
    db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    if os.Getenv("DEBUG") == "true" {
        db = db.Debug()  // 只有 DEBUG=true 时才开启
    }
    DB = db
}

启动服务时加上环境变量即可:

bash 复制代码
DEBUG=true ./my-app

这样生产环境不会误打印,开发环境一键开启,非常灵活。


方式二:单条查询临时 Debug(最精准)

如果全局打印太多,你只想看某一条 SQL,可以在查询链上临时加 .Debug()

go 复制代码
// 只打印这条查询的 SQL
db.Debug().Where("status = ?", 1).Find(&users)

// 其他查询不受影响
db.Where("role = ?", "admin").Find(&admins)  // 这条不会打印

适合场景: 只想排查某个特定查询,不想被大量日志淹没。

这种方式非常轻量,不需要改任何配置,用完把 .Debug() 删掉就行。


方式三:自定义 Logger(最专业)

如果你需要更精细的控制------比如只想打印慢查询、想把 SQL 写到文件而不是终端、想在日志中加上请求ID等上下文------就需要自定义 GORM 的 Logger。

go 复制代码
import (
    "log"
    "os"
    "time"
    "gorm.io/gorm/logger"
)

newLogger := logger.New(
    log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
    logger.Config{
        SlowThreshold:             200 * time.Millisecond, // 慢查询阈值
        LogLevel:                  logger.Info,            // 日志级别
        IgnoreRecordNotFoundError: true,                   // 忽略 ErrRecordNotFound
        Colorful:                  true,                   // 彩色打印
    },
)

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

关键参数解释:

参数 作用
SlowThreshold 超过这个时间的查询会被标记为慢查询,单独警示
LogLevel Silent 不打印、Error 只打印错误、Warn 打印错误+慢查询、Info 打印所有
IgnoreRecordNotFoundError 是否忽略 "记录未找到" 这种常见错误(避免日志刷屏)
Colorful 终端输出是否带颜色,方便区分不同级别

适合场景: 生产环境监控、慢查询分析、日志持久化到文件等进阶需求。


三种方式对比

方式 影响范围 使用难度 适用场景
全局 db.Debug() 所有 SQL ★☆☆ 开发环境整体调试
单条 .Debug() 仅该条查询 ★☆☆ 临时排查某条查询
自定义 Logger 可精细控制 ★★★ 生产环境/慢查询监控

小结

日常开发中,方式一 + 方式二 就够用了:全局 Debug 看整体,单条 Debug 看细节。当你需要上生产环境做监控时,再考虑方式三自定义 Logger。

相关推荐
ClouGence14 小时前
Oracle 数据同步为什么会出现数据不一致?长事务是常被忽略的原因
数据库·后端·oracle
飞将16 小时前
从零实现数据库(2)——HashIndex + IndexManager
数据库
Nturmoils2 天前
订单列表慢查询,先看 WHERE、ORDER BY 和 LIMIT
数据库
渣波2 天前
拒绝 SQL 焦虑!手把手带你用 NestJS + Prisma + DTO 写出“防弹”级后端代码
javascript·数据库·后端
倔强的石头_3 天前
KingbaseES 新版MySQL 兼容版体验:旧版迁移 + 功能实测
数据库
zzzzzz3104 天前
9K Star 炸裂开源!这个 C 语言写的代码知识图谱,把 Linux 内核索引压缩到了 3 分钟
linux·服务器·sql
倔强的石头_6 天前
《Kingbase护城河》——数据库存储空间全景探测与精细化瘦身实战
数据库
云技纵横6 天前
唯一索引 INSERT 死锁实战:5 秒复现交叉插入的 S 锁循环等待
sql·mysql
冬奇Lab6 天前
每日一个开源项目(第134篇):Zvec - 阿里开源的嵌入式向量数据库,向量搜索界的 SQLite
数据库·人工智能·llm
ClouGence7 天前
Oracle CDC 架构优化:从主库直连到 DataGuard 备库同步
数据库·后端·oracle