AutoMigrate没建表主因是传参或标签错误:必须传结构体指针&User{},ID字段需显式加gorm:"primaryKey",外键字段要配对声明且初始化时关闭DisableForeignKeyConstraintWhenMigrating。

db.AutoMigrate(&User{}) 为什么没建表?
最常见的情况是函数调用后数据库里空空如也,连表名都看不到。这不是 GORM 失效,而是它压根没“认出”你的结构体该映射成什么。
必须同时满足三个条件:
- 传入结构体指针:
&User{}—— 传User{}或new(User)都不行,GORM 依赖指针才能读取gorm标签 - ID 字段不自动当主键:哪怕字段叫
ID uint,也得显式加gorm:"primaryKey" - 外键字段要配对声明:比如
CompanyID uint,必须配合Company Company `gorm:"foreignKey:CompanyID"`,否则不会生成外键约束
另外,MySQL 默认禁用外键迁移,初始化 DB 时得关掉开关:DisableForeignKeyConstraintWhenMigrating: false,否则所有 foreignKey 标签全被忽略。
字段改了但数据库没变?类型变更不是全自动的
AutoMigrate 不会猜你意图,也不会盲目执行 ALTER COLUMN。它只在驱动支持 + 标签明确的前提下才改类型。
-
Age int→Age int64:默认不做任何事,必须加gorm:"type:bigint"显式声明 -
Age int→Age *int(允许 NULL):GORM 会尝试把列从NOT NULL改为可空,但 MySQL 5.7+ 才稳定支持;旧版可能静默失败 -
Content string→Content string `gorm:"size:2000"`:MySQL/PostgreSQL 会扩长度,SQLite 不支持ALTER COLUMN,会重建整张表(大表危险)
生产环境跑 AutoMigrate 前必须验证的三件事
它永远静默跳过“无需操作”的情况 —— 表已存在、字段已就位、外键开关关着……它都不会报错,更不会告诉你“什么都没干”。上线前务必主动确认:
- 用
db.Migrator().HasTable(&User{})检查表是否存在 - 用
db.Migrator().HasColumn(&User{}, "email")确认关键字段已落地 - 用
db.Migrator().HasIndex(&User{}, "idx_users_email")验证索引是否生效(尤其唯一索引)
别信日志里那句 “AutoMigrate success”,它只表示函数没 panic,不代表结构真的同步了。
批量迁移多个模型比循环调用更可靠
一次传多个指针,GORM 能自动理清外键依赖顺序,避免因建表顺序错误导致外键创建失败。
- 推荐写法:
db.AutoMigrate(&User{}, &Order{}, &UserRole{}) - 不推荐:
db.AutoMigrate(&User{}); db.AutoMigrate(&Order{})—— 中间若涉及外键引用,可能因UserRole表还没建而静默失败 - 要指定引擎或字符集?先
db.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"),再跑AutoMigrate
多对多中间表(如 UserRole)GORM 绝对不自动生成,必须自己定义 struct 并包含在 AutoMigrate 参数中。


















