GORM V2 必须从 gorm.io 导入驱动并下划线导入,DSN 需含 parseTime=True&loc=Local(MySQL)或 timezone(PostgreSQL),AutoMigrate 仅新增字段不修改删除,gorm.Model 自动覆盖时间字段,软删除需 Unscoped() 查询全部。

直接能用,但必须严格按 V2 规范来,否则 gorm.Open 会静默失败或 time 字段全为零值。
安装 gorm 和对应数据库驱动必须分开且带下划线导入
GORM V2 不再兼容旧版 github.com/jinzhu/gorm,所有依赖都得从 gorm.io 域名拉取。驱动不能只装 gorm.io/gorm,还必须显式安装并下划线导入具体驱动:
go get -u gorm.io/gorm-
go get -u gorm.io/driver/mysql(MySQL)或go get -u gorm.io/driver/postgres(PostgreSQL) - 代码里必须写
import _ "gorm.io/driver/mysql",不能省略下划线 —— 否则mysql.Open返回 nil,gorm.Open会 panic 报invalid driver name
DSN 必须包含 parseTime=True&loc=Local,否则 time.Time 字段失效
哪怕数据库里存的是合法时间,只要 DSN 缺这两个参数,CreatedAt、UpdatedAt 或自定义 time.Time 字段在 Go 中全解析成零值(如 0001-01-01 00:00:00 +0000 UTC),且不报错,只在后续逻辑中暴露异常。
- MySQL 正确示例:
"root:pass@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local" - PostgreSQL 正确示例:
"host=localhost port=5432 user=postgres password=mypassword dbname=mydb sslmode=disable"(PostgreSQL 驱动不强制要求parseTime,但建议统一加&timezone=Asia/Shanghai避免时区错乱) - 别信网上老教程里
github.com/go-sql-driver/mysql的 DSN 写法,GORM V2 完全不认
AutoMigrate 只做加法,改字段或删列得手动处理
db.AutoMigrate(&User{}) 看起来像“一键同步”,实际行为非常保守:它只会新增表、新增字段、新增索引,绝不会修改已有字段类型、长度、默认值,也绝不会删除任何列。
立即学习“go语言免费学习笔记(深入)”;
- 把
Name string `gorm:"size:32"`改成size:64,再次调用AutoMigrate没反应 - 删掉结构体字段,对应数据库列还在,下次
Create可能因 NOT NULL 约束失败 - 想改类型?得手写
ALTER TABLE,或引入gormigrate等迁移工具 - 开发阶段可接受,但上线前必须人工比对模型与表结构是否一致,否则
Scan可能截断、Create可能丢字段
gorm.Model 自带时间字段有隐式覆盖逻辑
用 type User struct { gorm.Model } 确实省事,但它强制注入 CreatedAt、UpdatedAt、DeletedAt,且这些字段在 INSERT/UPDATE 时自动赋值 —— 即使你从 JSON 解析时已经设了值,GORM 也会覆盖。
- 想保留自己设置的时间?得关掉自动更新:
db.Session(&gorm.Session{AllowGlobalUpdate: true}).Create(&user)不够,要显式禁用钩子:db.WithContext(context.WithValue(ctx, gorm.ErrInvalidData, true)).Create(&user)更推荐方式是:去掉gorm.Model,自己定义 ID 和时间字段,并用gorm:"default:current_timestamp"控制数据库侧默认值 -
DeletedAt启用软删除后,所有Find默认过滤掉已删记录,查全部得加Unscoped() - 时间字段类型统一用
time.Time,别混用int64或字符串,否则关联查询或预加载易出错
真正麻烦的不是连不上数据库,而是连上了却读不到时间、字段对不上、迁移没反应——这些坑都不报错,只等业务逻辑跑通一半才崩。


















