gorm v2 必须用 mysql.open(dsn) 传参,禁用字符串 "mysql";dsn 需含 parsetime=true&loc=local;连接池须手动配置 maxopenconns 等参数;automigrate 不建库、只增字段;表名默认复数,单数需显式配置 namingstrategy。

gorm.Open 传参方式必须匹配 v2 版本签名
GORM v2 不再接受 "mysql" 字符串 + DSN 的老式写法,直接用 gorm.Open("mysql", dsn) 会编译报错:类型不匹配。v2 要求第一个参数是实现了 Dialector 接口的对象,比如 mysql.Open(dsn)。
常见错误现象:cannot use "mysql" (type string) as type gorm.Dialector 或 too many arguments。
- 必须先
go get -u gorm.io/driver/mysql(不是github.com/jinzhu/gorm) - 导入时用
import "gorm.io/driver/mysql",不是旧版的github.com/jinzhu/gorm/dialects/mysql -
dsn格式要带tcp(127.0.0.1:3306),不能只写127.0.0.1:3306;末尾推荐加上&parseTime=True&loc=Local,否则time.Time字段可能解析失败
初始化后必须显式配置连接池
刚调用 gorm.Open 得到的 *gorm.DB 对象默认连接池极小(MaxIdleConns=1, MaxOpenConns=10),高并发下容易卡死或报 dial tcp: i/o timeout。
正确做法是在 Open 后立刻调用底层 *sql.DB 的配置方法:
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic(err)
}
sqlDB, err := db.DB()
if err != nil {
panic(err)
}
sqlDB.SetMaxIdleConns(10)
sqlDB.SetMaxOpenConns(100)
sqlDB.SetConnMaxLifetime(time.Hour)
注意:SetConnMaxLifetime 是防连接僵死的关键,MySQL 默认 wait_timeout 是 8 小时,设为 1 小时更稳妥。
AutoMigrate 不等于建库,表名复数规则要提前确认
db.AutoMigrate(&User{}) 只会在已有数据库里创建表(或加字段),不会自动创建数据库本身。如果 dsn 中的 dbname 不存在,会报错 Error 1049: Unknown database 'xxx'。
另外 GORM 默认把结构体名转成复数作表名(User → users),但你的 SQL 建表语句里是 users,这刚好匹配;如果想强制用单数名(如 user),得在 gorm.Config 里开开关:
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
NamingStrategy: schema.NamingStrategy{SingularTable: true},
})
没配这个又定义了 type User struct{...},却期望生成 user 表,就会查不到数据——因为实际建的是 users 表,而你查询时没指定表名,GORM 还是按复数找。
全局 DB 实例该存在哪、怎么传
别在每个 handler 里重复 gorm.Open,也别用包级变量裸奔(比如 var DB *gorm.DB),容易引发并发写 panic 或测试难 mock。
推荐方式是:在 main() 或服务初始化函数中完成 Open + 连接池配置,然后作为依赖注入到各 service 层:
- 定义一个
type Repository struct { DB *gorm.DB },所有数据操作方法都绑在它上面 - 初始化时 new 出来,把
*gorm.DB塞进去,再传给 API handler 或 usecase - 如果用 go-zero,就塞进
svcCtx;自己写框架就塞进 config struct 或 app context
最易被忽略的一点:GORM 的 *gorm.DB 本身是线程安全的,可复用,但它内部的 Session(比如带 WithContext 或 Debug 的)不是长期持有的对象——每次请求应基于它 clone 新 session,而不是全局存一个带 context 的 DB 实例。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











