必须用 logger.config 配置 loglevel: logger.debug 且显式设置 parameterizedqueries: true,否则日志仅显示带问号的 sql 模板;logmode(true) 在 gorm v2 中已移除,需在 gorm.open 时通过 gorm.config.logger 注入。

必须用 logger.Config 配置 LogLevel: logger.Debug,且显式设置 ParameterizedQueries: true,否则看到的只是带问号的 SQL 模板,不是真实执行语句。
为什么 LogMode(true) 在新版本 GORM v2 中失效了
因为 LogMode() 是 v1 的遗留方法,v2 已移除。调用它会直接 panic 或静默忽略——这不是配置没生效,而是方法根本不存在。所有日志控制必须在初始化 gorm.Open() 时通过 gorm.Config.Logger 注入。
- 检查你的 import:必须是
"gorm.io/gorm/logger",不是旧版"github.com/jinzhu/gorm" - 确认
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{ Logger: newLogger })这一行已写死,不能靠运行时调用db.LogMode(true) - 如果用了
gin或其他框架封装了 DB 初始化,要找到最终调用gorm.Open的位置改配置,而不是在 handler 里补
ParameterizedQueries: true 不起作用的常见原因
即使开了 Debug 级别,若没设 ParameterizedQueries: true,日志里只会显示 SELECT * FROM users WHERE id = ?,参数值不会展开。更隐蔽的问题是:这个字段只在 LogLevel == logger.Debug 时才生效,Info 级别下设了也白设。
-
SlowThreshold和ParameterizedQueries是独立开关,前者控制慢 SQL 标记,后者控制参数拼接,别以为设了阈值就自动带参数 - 终端输出时建议同时开
Colorful: true,SQL 部分会高亮,一眼就能从一堆日志里揪出来 - 如果用
logrus或zap接管日志输出,确保传给logger.New()的io.Writer是你自定义 logger 的Out字段,而不是直接写os.Stdout
开发环境自动开、生产环境自动关的稳妥做法
别用 if os.Getenv("ENV") == "dev" 包裹整个 logger 创建逻辑——这容易漏掉环境变量读取时机或拼写错误。推荐用构建标签或初始化时硬编码判断。
- 在 main.go 开头加
//go:build debug,然后单独写一个logger_debug.go文件,里面只定义 debug 模式下的 logger 实例 - 或者统一读配置项:
env := os.Getenv("GIN_MODE"); if env == "debug" || env == "release" && os.Getenv("SQL_LOG_ENABLED") == "true",但后者需文档明确约定开关名 - 绝对禁止在高频查询如
db.Where(...).Find()前临时加db.Session(&gorm.Session{Logger: debugLogger}).First(),这会覆盖当前 session 的 logger,且无法保证事务一致性
最易被忽略的一点:Debug 日志不仅打 SQL,还会打印结构体反射过程、钩子调用栈、事务边界等——哪怕你只想要 SQL,也得接受这些额外信息。真要干净输出,得自己实现 gorm.Logger 接口并重写 Trace() 方法,只保留 SQL 和 RowsAffected 字段。











