4. AutoMigrate 入门:基本用法与自动建表
AutoMigrate 是 GORM 提供的最便捷的数据库迁移入口。它允许开发者通过 Go 结构体定义模型,然后由 GORM 自动在数据库中创建、更新表结构,而无需手写 DDL 语句。本章将系统讲解 AutoMigrate 的核心用法、自动建表、自动增加字段以及自动修改字段类型。
4.1 AutoMigrate 基本用法
AutoMigrate 的核心方法是 db.AutoMigrate(&Model{}),它接收一个或多个模型指针,GORM 会根据模型定义自动同步数据库表结构。其执行逻辑如下:
- 表不存在:自动创建新表。
- 表已存在,字段缺失:自动增加新字段。
- 表已存在,字段类型变更:自动修改字段类型(仅支持部分数据库)。
- 表已存在,字段多余:不会删除字段,保证数据安全。
4.2 自动建表示例
以下代码演示如何使用 AutoMigrate 自动创建 users 表:
package main
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type User struct {
ID uint `gorm:"primaryKey"`
Name string `gorm:"size:100;not null"`
Email string `gorm:"uniqueIndex;size:255"`
Age uint8
CreatedAt time.Time
UpdatedAt time.Time
}
func main() {
dsn := "root:password@tcp(127.0.0.1:3306)/testdb?charset=utf8mb4&parseTime=True"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("数据库连接失败")
}
// 自动迁移:创建 users 表
err = db.AutoMigrate(&User{})
if err != nil {
panic("自动迁移失败")
}
}
执行后,数据库中将自动生成 users 表,包含 id、name、email、age、created_at、updated_at 六个字段,主键、唯一索引、非空约束等均已生效。
4.3 自动增加字段
当业务需求变更,需要为已有表增加字段时,只需在结构体中添加新字段,再次执行 AutoMigrate 即可。
假设 User 表需要增加 Phone 和 Status 字段:
type User struct {
ID uint `gorm:"primaryKey"`
Name string `gorm:"size:100;not null"`
Email string `gorm:"uniqueIndex;size:255"`
Age uint8
Phone string `gorm:"size:20"` // 新增字段
Status int `gorm:"default:1"` // 新增字段
CreatedAt time.Time
UpdatedAt time.Time
}
// 再次执行迁移
db.AutoMigrate(&User{})
GORM 会自动检测 users 表中缺少 phone 和 status 列,并执行 ALTER TABLE 添加这两列。已有数据不受影响,新列会使用默认值填充。
4.4 自动修改字段类型
当字段的 GORM 标签或 Go 类型发生变化时,AutoMigrate 会尝试修改字段类型。但不同数据库的支持程度不同:
| 数据库 | 支持修改字段类型 | 注意事项 |
|---|---|---|
| MySQL | ✅ 支持 | 使用 ALTER TABLE MODIFY,可能因数据不兼容而失败 |
| PostgreSQL | ✅ 支持 | 使用 ALTER TABLE ALTER COLUMN,类型转换规则严格 |
| SQLite | ❌ 不支持 | SQLite 不支持 ALTER COLUMN,需重建表 |
| SQL Server | ✅ 支持 | 使用 ALTER TABLE ALTER COLUMN |
示例:将 Age 字段从 uint8 改为 uint16:
type User struct {
ID uint `gorm:"primaryKey"`
Name string `gorm:"size:100;not null"`
Email string `gorm:"uniqueIndex;size:255"`
Age uint16 // 类型从 uint8 改为 uint16
Phone string `gorm:"size:20"`
Status int `gorm:"default:1"`
CreatedAt time.Time
UpdatedAt time.Time
}
db.AutoMigrate(&User{})
在 MySQL 中,GORM 会执行 ALTER TABLE users MODIFY COLUMN age smallint unsigned。如果表中已有数据超出新类型的范围,迁移会失败并返回错误。
4.5 AutoMigrate 迁移流程
下图展示了 AutoMigrate 从模型定义到数据库表同步的完整流程:
4.6 多模型迁移
AutoMigrate 支持同时迁移多个模型,GORM 会按顺序处理每个模型:
type Order struct {
ID uint `gorm:"primaryKey"`
UserID uint
Product string
Amount float64
}
type Product struct {
ID uint `gorm:"primaryKey"`
Name string
Price float64
}
// 同时迁移多个表
db.AutoMigrate(&User{}, &Order{}, &Product{})
执行后,数据库中会创建 users、orders、products 三张表。如果某张表已存在,则只进行增量同步。
4.7 常见问题与避坑
- 字段标签变更:修改
gorm标签(如size、not null)不会触发字段修改,AutoMigrate 只关注 Go 类型变化。 - 索引变更:新增索引标签(如
uniqueIndex)会自动创建索引,但移除标签不会删除已有索引。 - 外键约束:AutoMigrate 不会自动创建外键约束,需使用
gorm:"constraint"标签或手动迁移。 - 并发安全:多个实例同时执行 AutoMigrate 可能导致冲突,建议在应用启动时单例执行。