正确初始化需三步:1. 导入gorm.io/driver/mysql并下划线导入;2. dsn必须含parsetime=true&loc=local;3. 调用gorm.open(mysql.open(dsn), &gorm.config{})。

能直接跑通的 GORM 数据库操作,核心就三步:连上 DB、定义模型、调用方法。跳过抽象概念,先让数据动起来。
如何正确初始化 gorm.Open 并避免连接失败
连接失败八成出在 DSN 字符串或驱动导入上。GORM v2(gorm.io/gorm)和旧版(github.com/jinzhu/gorm)的写法完全不同,混用必报错。
- 必须用
gorm.io/driver/mysql(或其他对应驱动),不能只导入gorm.io/gorm - DSN 中
parseTime=True和loc=Local缺一不可,否则time.Time字段会变成零值或 panic - MySQL 8+ 默认用 caching_sha2_password 插件,Go 驱动不兼容,需改用户认证方式:
ALTER USER 'user'@'%' IDENTIFIED WITH mysql_native_password BY 'pass'; - 示例连接代码(v2):
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
dsn := "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic(err)
}
定义结构体模型时,gorm.Model 和自定义字段标签怎么选
直接内嵌 gorm.Model 最省事,它自动带 ID、CreatedAt、UpdatedAt、DeletedAt(软删除用)。但如果你的表主键不是 id 或类型不是 uint,就得手动声明。
- 主键非
ID:用gorm:"primaryKey"标签,比如UserID uint `gorm:"primaryKey"` - 字段名与列名不一致:用
gorm:"column:email_address" - 想跳过某个字段不映射:加
gorm:"-",比如Password string `gorm:"-"` - 唯一索引 + 非空:写成
Email string `gorm:"uniqueIndex;not null"`,别只写unique(它只建索引,不加约束)
AutoMigrate 建表后,为什么字段没按预期创建
AutoMigrate 不是“同步结构体到表”,而是“按当前结构体尝试建表或新增字段”,它不会删字段、改类型、删索引。常见坑:
- 改了结构体字段类型(比如
string→*string),AutoMigrate不会改列类型,得手动ALTER TABLE - 加了
gorm:"default:1",但 MySQL 表里没生效?检查是否用了DEFAULT关键字 —— GORM v2 要配合gorm:"default:1"+sql.NullInt64等可空类型才可靠 - 想建联合唯一索引?用
gorm:"uniqueIndex:idx_user_email",多个字段都加同一索引名即可 - 首次运行务必确认数据库存在,
AutoMigrate不会自动创建 database
CRUD 操作中容易忽略的返回值和链式调用陷阱
GORM 方法大多返回 *gorm.DB,支持链式调用,但每个方法执行时机不同。最常踩的坑是以为 Where + First 是原子操作,其实中间可以插入 Debug() 或 Session()。
-
First()找不到记录时返回ErrRecordNotFound,不是nil错误,别直接if err != nil判定业务失败 -
Create()成功后,传入结构体的ID字段会被自动赋值;但Save()对已有 ID 的结构体是 update,无 ID 才 insert —— 容易误覆盖 -
Updates()传map[string]interface{}会更新所有 key 对应字段;传结构体则只更新非零值字段(0、""、nil都被忽略) - 批量插入用
CreateInBatches(&users, 100),别直接Create(&users)—— 否则生成超长 SQL,MySQL 可能报Packet too large
真实项目里,AutoMigrate 只用于本地开发或测试环境;生产环境必须用迁移工具(如 golang-migrate)管理 SQL 变更。GORM 的便利性背后,是对 SQL 控制力的让渡 —— 该写原生 SQL 的时候,别硬套 ORM。











