news 2026/4/17 16:10:50

gorm 1.X db日志 SELECT count(*) FROM “users“ WHERE “users“.“deleted_at“ IS NULL AND ((id = $1)) LIMIT

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
gorm 1.X db日志 SELECT count(*) FROM “users“ WHERE “users“.“deleted_at“ IS NULL AND ((id = $1)) LIMIT

这个 GORM 1.x 的 SQL 日志问题。

问题现象

你的 SQL 日志显示:

sql

复制

SELECT count(*) FROM "users" WHERE "users"."deleted_at" IS NULL AND ((id = $1)) LIMIT 1 OFFSET 0 [1929496158825091072] 0

你期望的是:

sql

复制

SELECT count(*) FROM "users" WHERE "users"."deleted_at" IS NULL AND id = 1929496158825091072 LIMIT 1 OFFSET 0

原因分析

这是GORM 1.x 的正常日志行为,不是 Bug:

表格

复制

日志组件行为说明
GORM 内置 Logger出于安全考虑,默认使用占位符$1而非直接拼接参数值
参数列表[1929496158825091072]显示在 SQL 语句之后,表示实际绑定的参数值

解决方案

方案一:启用完整 SQL 打印(调试用途)

go

复制

// 开启详细日志,包含完整 SQL db.LogMode(true) // 或者自定义 Logger,使用 Print SQL 模式 db.SetLogger(gorm.Logger{LogWriter: log.New(os.Stdout, "\r\n", 0)}) db.LogMode(true) // GORM 1.x 中让参数直接拼接到 SQL(不推荐生产环境使用) db.Callback().Query().Register("log", func(scope *gorm.Scope) { // 通过 scope.SQL 和 scope.Vars 手动拼接 log.Println(scope.SQL, scope.Vars) // 这里可以自行格式化输出 })

方案二:自定义 Logger 实现参数内联

go

复制

import ( "log" "os" "fmt" "github.com/jinzhu/gorm" ) // 自定义 Logger type CustomLogger struct{} func (l CustomLogger) Print(v ...interface{}) { if len(v) >= 4 { level := v[0] source := v[1] if level == "sql" { // v[3] 是 SQL 语句,v[4] 是参数数组 sql := v[3].(string) vars := v[4] // 打印带参数的完整 SQL(仅调试用途) fmt.Printf("[SQL] %s | 参数: %v | 来源: %v\n", sql, vars, source) return } } // 其他日志走默认输出 log.New(os.Stdout, "\r\n", 0).Print(v...) } // 使用自定义 Logger db.SetLogger(CustomLogger{}) db.LogMode(true)

方案三:使用第三方 GORM 日志工具

go

复制

import gormlog "github.com/op/go-logging" // 或使用 go-sql-driver/mysql 的 interpolateParams // 但这需要数据库驱动层支持

为什么使用占位符更好?

go

复制

// ❌ 不安全:SELECT ... WHERE id = 192949... // 如果参数包含恶意字符:id = "1 OR 1=1 --",会导致 SQL 注入 // ✅ 安全:使用预处理语句 // 数据库驱动会将参数与 SQL 分离处理

验证实际执行的 SQL

如果你想确认数据库实际收到的 SQL,可以在数据库层面查看:

bash

复制

# PostgreSQL SHOW log_min_duration_statement; SET log_min_duration_statement = 0; -- 记录所有语句 # MySQL SET GLOBAL general_log = 'ON'; SHOW VARIABLES LIKE 'general_log%';

总结$1占位符 + 参数列表的日志格式是 GORM 的设计特性,代表使用了预处理语句(Prepared Statement),这是安全且推荐的做法。如果你确实需要内联参数用于调试,可以使用上述方案二自定义 Logger。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 9:09:16

2025年AI工具定价指南:主流平台技术特性与成本效益分析

2025 AI工具定价指南:哪个平台适合您? 人工智能工具已成为我们日常生活不可或缺的一部分。然而,市场上数十种不同的选择,使得挑选最适合您需求且在预算内提供最佳价值的工具,变成了一个相当复杂的过程。根据我20多年的…

作者头像 李华
网站建设 2026/4/16 18:46:28

Clawdbot背后的技术原理,吴恩达出官方课程了

Datawhale干货 最新:吴恩达 Agent Skill 课程如果你最近刷科技圈,一定见过那只红色龙虾——Clawdbot(现已改名 OpenClaw)。短短一周,12 万 GitHub stars。增长速度快到离谱,社交平台上到处都是开发者在晒截…

作者头像 李华
网站建设 2026/4/18 3:22:50

AI驱动的下一代邮箱安全架构——多层智能防护与高级威胁过滤机制深度剖析

【精选优质专栏推荐】 《AI 技术前沿》 —— 紧跟 AI 最新趋势与应用《网络安全新手快速入门(附漏洞挖掘案例)》 —— 零基础安全入门必看《BurpSuite 入门教程(附实战图文)》 —— 渗透测试必备工具详解《网安渗透工具使用教程(全)》 —— 一站式工具手册《CTF 新手入门实战教…

作者头像 李华