logmode(false) 是最直接、最可靠的关闭方式,需在初始化数据库连接后立即调用,且每个 *gorm.db 实例都须单独设置,否则 sql 日志仍会输出。

LogMode(false) 是最直接、最可靠的关闭方式
很多人误以为只要不调用 Debug() 就不会输出 SQL 日志,其实不然。GORM 的日志开关是连接级别的,LogMode(true) 一旦启用,所有后续操作(包括 Find、Preload、Create)都会打日志,且不会自动恢复。生产环境必须显式关掉它。
正确做法是在初始化数据库连接后,立即调用 LogMode(false):
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// 立即关闭日志,哪怕只在开发环境开了也要确保这里关掉
db.LogMode(false)
- 不要依赖环境变量或配置判断后才决定是否调用
LogMode(false)—— 它本身开销极小,强制执行更安全 - 如果使用了自定义 logger(如 zap 或 logrus),仍需调用
LogMode(false),否则 GORM 内部仍会触发日志回调 -
LogMode(false)不影响错误日志(Error级别)和警告日志(Warn级别),只禁用Info级别的 SQL 输出
为什么不能只靠 logger.Level 控制?
GORM v2 的日志行为由两层控制:全局 LogMode + logger 实例的 Config.LogLevel。即使你把 Config.LogLevel 设为 logger.Silent,若 LogMode(true) 已生效,GORM 仍会尝试调用 logger 的 Info 方法 —— 这时如果 logger 没有实现 Info,可能 panic 或静默失败,行为不可控。
所以关键点是:LogMode 是总闸,LogLevel 是分流阀。生产环境必须先关总闸。
检查是否真关掉了:看日志里还有没有 “sql:” 开头的行
最简单的验证方式:在生产启动后,执行一条简单查询(比如 db.First(&user, 1)),然后 grep 日志:
grep "sql:" app.log
- 如果有输出,说明
LogMode(true)还在生效,或者某处代码意外重开了(比如测试代码残留、中间件里调了Debug()) - 注意:某些自定义 logger(如用
log.Println包装的)可能把 SQL 打到 stderr,要一并检查 - SQLite 驱动对日志控制较弱,若用它做本地测试,务必单独验证,避免误判 MySQL 行为
真正容易被忽略的是:LogMode 是连接实例级别的,不是全局单例。如果你用了多个 *gorm.DB 实例(比如主从分离、多租户),每个都得单独调一次 LogMode(false)。











