默认不打印sql,需显式配置logger;最可靠方式是设loglevel为debug并启用parameterizedqueries,仅debug级生效,info级只显示问号占位符sql。

开启 GORM 的 SQL 日志输出
默认情况下,GORM 不打印任何 SQL 语句。要看到它实际执行了什么,必须显式启用日志器。最直接的方式是用 Config.Logger 配置一个带 Debug 级别的日志器。
- 使用
GormLogger(v2+ 推荐):传入log.Info或自定义的logger,并设置LogLevel: logger.Info或logger.Info;logger.Info只显示 SQL 和行数,logger.Info还会显示执行耗时和参数值 - 快速调试可直接用
logger.Default.LogMode(logger.Info),但注意这会影响全局日志级别 - 若用
db.Debug(),只对单次调用生效,适合临时排查某条查询,不建议长期开启
避免日志污染生产环境
开发时开日志很爽,但上线后没关掉会导致 I/O 暴增、磁盘写满,甚至拖慢数据库响应。GORM 日志不是“开关式”配置,而是随 *gorm.DB 实例携带的——不同实例可以有不同日志级别。
- 推荐按环境初始化 DB:开发环境用
logger.Info,测试/生产用logger.Warn或logger.Error - 不要在中间件或通用 DB 初始化函数里无条件调用
db.Logger.LogMode(...),否则所有环境都会被覆盖 -
db.Session(&session.Options{Logger: newLogger})可为特定操作临时换日志器,比Debug()更可控
常见日志不输出的原因
写了配置却看不到 SQL,大概率卡在这几个点上:
- 用了
gorm.Open(...)但没把返回的*gorm.DB赋值给变量,导致后续调用的是未配置日志的默认实例 - 误以为
db.LogMode(...)是全局设置,其实它是链式方法,必须写成db = db.LogMode(...)才生效(v1 写法,v2 已废弃) - 日志输出被重定向到
ioutil.Discard或空io.Writer,检查logger.Config.Output是否指向了有效 writer - 事务内执行的 SQL 不会单独触发日志(除非开启
PrepareStmt: true),因为 GORM v2 默认复用 prepared statement,日志只在首次预编译时打印
查看带参数的完整 SQL(含问号替换)
GORM 默认只打印带 ? 占位符的 SQL,不展开参数值。想看到真实执行语句(比如确认 WHERE id = 123),需开启 logger.Info 级别并确保 Config.PrepareStmt 为 true(v2 默认开启)。
-
logger.Info级别下,GORM 会尝试将参数值格式化进 SQL 字符串,但注意:字符串中的单引号、NULL 值、时间格式等仍可能与数据库实际解析不完全一致 - 真正 100% 看到数据库收到的原始字节,得去数据库侧查 slow log 或启用
general_log(MySQL)——GORM 日志终究是“模拟拼接”,不是抓包 - 如果发现参数没被替换(依然显示
?),检查是否误用了Raw()或Exec()且未手动启用Debug()
*gorm.DB 实例,以及是否理解 PrepareStmt 和日志级别的交互逻辑。











