automigrate是结构同步器,只安全补全:建表、加字段、扩类型、加索引/外键;不删字段、不改字段名、不降级not null,须传指针、配标签、显式处理外键与中间表。

AutoMigrate 不是“一键同步工具”,它只做安全补全:建表、加字段、扩类型、加索引/外键;删字段、改字段名、降级 NOT NULL 都不会自动发生。
传指针、配标签、别漏外键开关
AutoMigrate(&User{}) 什么也不干,大概率是因为你传了 User{} 而不是 &User{} —— 它必须接收结构体指针才能读取字段标签。常见踩坑点:
- ID 字段不加
gorm:"primaryKey"标签,GORM 可能忽略主键或报错(即使叫ID) - 外键字段如
CompanyID uint,得配合关联字段写Company Company `gorm:"foreignKey:CompanyID"`,否则外键约束不会生成 - MySQL 默认禁用外键迁移:初始化 DB 时要显式设
DisableForeignKeyConstraintWhenMigrating: false,否则foreignKey标签无效 - 多对多中间表(如
UserRole)GORM 绝对不自动生成,必须自己定义 struct 并单独调AutoMigrate(&UserRole{})
字段类型变更到底能不能生效?
不是所有类型改动都会触发 ALTER COLUMN。GORM 的行为取决于数据库驱动能力和你写的标签:
-
Name string→Name string `gorm:"size:100"`:MySQL/PostgreSQL 会改长度;SQLite 不支持,直接重建表(大表危险) -
Age int→Age *int(允许 NULL):GORM 会尝试把列从NOT NULL改成可空,但前提是驱动支持(MySQL 5.7+ OK,旧版可能失败) -
Age int→Age int64:默认不升级类型!需加gorm:"type:bigint"显式声明,否则字段在库中仍是INT - 想让 GORM 在 MySQL 8 之前更稳妥地处理重命名列?初始化时加配置
DontSupportRenameColumn: true,让它用CHANGE COLUMN替代RENAME COLUMN
批量迁移和表选项怎么控制?
一次迁多个模型比循环调用快,还能自动理清外键依赖顺序:
- 推荐写法:
db.AutoMigrate(&User{}, &Order{}, &UserRole{}),而非三次单独调用 - 要指定引擎或字符集?先
db.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"),再跑AutoMigrate - SQLite 或老 MySQL(
最易被忽略的是:AutoMigrate 永远不会告诉你“这次没做任何事”。它静默跳过所有它认为无需操作的情况,包括字段已存在、类型无需变更、外键开关关着……上线前最好用 db.Migrator().HasTable(&User{}) 和 db.Migrator().HasColumn(&User{}, "email") 主动验证关键结构是否就位。











