gorm v2 panic 根因是传参方式错误:不再支持 gorm.open("mysql", dsn),须用 driver.open(dsn) 获取 *sql.db 后传入;automigrate 仅单向增量,不删改字段;where 对 map/struct 不过滤零值;事务需显式 commit 或用 db.transaction。

gorm.Open 为什么一调就 panic
根本原因不是 DSN 写错,而是传参方式错误:GORM v2 不再接受 "mysql" 和 dsn 两个字符串参数。直接写 gorm.Open("mysql", dsn) 会触发 panic: unsupported driver。
必须先用 database/sql 打开驱动,再把返回的 *sql.DB 实例传给 gorm.Open:
- MySQL:导入
gorm.io/driver/mysql,调用mysql.Open(dsn) - PostgreSQL:导入
gorm.io/driver/postgres,调用postgres.Open(dsn) - SQLite:导入
gorm.io/driver/sqlite,调用sqlite.Open("test.db")
示例(MySQL):
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
AutoMigrate 为什么没建表或字段缺失
AutoMigrate 不是“同步 schema”,它只做单向增量:新增表、新增字段、新增索引,但绝不会删字段、改类型、重命名列。一旦运行过,就别指望它回退。
常见漏点:
- 首字母小写的 struct 字段(如
name string)默认被 GORM 忽略,必须加gorm:"column:name"显式声明 - 字段类型不匹配(如 struct 用
int64,DB 列是BIGINT UNSIGNED),AutoMigrate会静默跳过该字段 - 外键关联字段类型不一致(如
UserID uint对应 DB 中INT),MySQL 8.0+ 严格模式下迁移失败但无报错,需开启日志:gorm.Config{Logger: logger.Default.LogMode(logger.Info)}
Where 传 map 或 struct 总是查不到数据
GORM 对 Where 的 map / struct 解析是浅层反射,不做零值过滤 —— ""、0、nil 都会被当有效条件生成 SQL。
例如:
Where(map[string]interface{}{"name": "", "age": 0})
实际生成:WHERE name = '' AND age = 0,而非“忽略空值”。
安全做法:
- 手动链式拼接:
Where("name != ?", "").Where("age > ?", 0) - struct 传参更危险:字段名必须与 DB 列名**完全一致(含大小写)**,
gorm:"column:user_name"不影响Where(&User{Name: "a"})的解析逻辑 - 需要动态条件时,优先用
map[string]interface{}+ 显式判断,而不是依赖结构体自动展开
事务里 Save/Create 数据没提交
在事务内调用 Save 或 Create,若没显式 Commit(),所有变更都会被丢弃 —— 即使函数返回成功,数据也从未落库。
典型错误写法:
tx := db.Begin() tx.Create(&user) // 忘了 tx.Commit() 或 tx.Rollback()
正确姿势:
- 用
defer确保 rollback:
tx := db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
if err := tx.Create(&user).Error; err != nil {
tx.Rollback()
return err
}
tx.Commit()
- 更推荐用
db.Transaction(func(tx *gorm.DB) error { ... }),自动处理 commit/rollback - 注意:事务内嵌套调用其他函数时,那些函数若用了全局
db实例,就脱离了当前事务上下文
SetMaxOpenConns)必须作用于原生 *sql.DB,不是 *gorm.DB;而 AutoMigrate 和 Where 这类行为,又只对 GORM 实例生效 —— 混淆这两层对象是最容易踩的隐性坑。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











