GORM连接失败主因是DSN或驱动“静默失效”:漏下划线导入、密码含@未URL编码、MySQL缺parseTime=True&loc=Local、PostgreSQL漏sslmode=disable/require及TimeZone设置。

GORM 连接数据库失败,八成不是代码写错了,而是 DSN 或驱动配置在“静默失效”——比如漏了 _ 导入、密码含 @ 没 URL 编码、或 MySQL 缺 parseTime=True 导致时间字段解析卡住。
DSN 中特殊字符没编码就 panic
PostgreSQL 或 MySQL 密码含 @、/、:、? 时,DSN 解析会提前截断,错误提示常是 pq: password authentication failed 或 invalid connection,完全不提“密码格式问题”。
- 必须用
url.QueryEscape()处理密码,例如P@ssw0rd→P%40ssw0rd - 用户名含特殊字符同理,但更少见;优先检查密码
- 别手写编码,Go 标准库
net/url提供的函数才是可靠解法
MySQL 连接后查不出数据或 time.Time 字段报错
典型现象:连接成功、表存在、SQL 手动执行正常,但 db.Find() 返回空结构体(如 {0 "" 0}),或插入时爆 Error 1292: Incorrect datetime value。
- DSN 必须带
parseTime=True,否则 GORM 无法把数据库时间转成 Go 的time.Time - 加上
loc=Local(或loc=Asia/Shanghai)才能避免时区偏移,否则created_at可能被当成 UTC 存入 - 若 MySQL 启用了严格模式(
STRICT_TRANS_TABLES),0000-00-00 00:00:00类时间值会被拒绝——要么改表默认值,要么关掉严格模式(不推荐生产环境)
PostgreSQL 连接卡住或时区差 8 小时
没报错但请求 hang 住,或者时间字段总比预期早/晚整数小时,基本锁定两个点。
- DSN 必须显式加
sslmode=disable(开发环境)或sslmode=require(生产),漏掉会卡在 TLS 握手阶段 - 务必追加
TimeZone=Asia/Shanghai,否则 PostgreSQL 返回 UTC 时间,GORM 默认按本地时区解析,Linux 服务器常是 UTC,导致显示偏差 -
connect_timeout=5建议加上,避免网络抖动时整个服务线程阻塞 30 秒
多数据源下 db 实例被覆盖或事务失效
微服务连多个库时,常见错误是只声明一个全局 var db *gorm.DB,反复 gorm.Open() 赋值,结果后开的库覆盖前一个,查库错乱、事务不起作用、甚至 panic。
- 每个库必须独立变量:如
userDB、logDB、cacheDB,各自调gorm.Open() - 驱动导入不能漏下划线:
import _ "gorm.io/driver/mysql"和import _ "gorm.io/driver/postgres",否则静默失败 - 事务只绑定到单个
*gorm.DB实例,userDB.Transaction()里调logDB.Create()完全不在事务内——这不是 bug,是设计限制
最易忽略的是 DSN 参数和驱动导入的耦合性:传 mysql.Open(dsn) 却填 PostgreSQL 的 DSN,GORM 不会在 Open() 阶段报错,而是在第一次查询时才暴露模糊错误。调试时得从 gorm.Open() 的第一个参数和 DSN 内容是否真正匹配开始核对。


















