不会。automigrate是“只增不减”的非破坏性操作,仅创建表、新增字段、添加索引,绝不会删除字段、修改类型、重命名列或清空数据,生产环境直接使用虽不丢数据,但无法完成结构重构,须配合手动迁移或显式方法。

AutoMigrate 会删字段或清数据吗?
不会。GORM 的 AutoMigrate 是“只增不减”的非破坏性操作:它只会创建缺失的表、新增字段、添加索引,但绝不会删除已有字段、修改字段类型、重命名列,更不会清空或修改现有数据。
这意味着你在生产环境直接调用 AutoMigrate 不会导致数据丢失,但也不能依赖它完成结构重构(比如把 string 字段改成 int)——这类变更必须手动写迁移脚本或使用 db.Migrator().AlterColumn() 等显式方法。
- 新增字段:自动加
ALTER TABLE ... ADD COLUMN - 新增唯一索引:自动执行
CREATE UNIQUE INDEX - 字段类型变更(如
size:100→size:255):GORM 不处理,需手动AlterColumn - 删除字段标签:该字段在数据库中仍存在,
AutoMigrate完全忽略
生产环境能直接用 AutoMigrate 吗?
可以,但必须加条件控制——默认开启等于裸奔。
GORM 不区分开发/生产环境,AutoMigrate 在任何环境下行为一致。如果你的启动逻辑里写了 db.AutoMigrate(&User{}, &Article{}),上线后每次重启都会触发检查,虽无破坏性,但会带来两个实际风险:
- 数据库锁表时间不可控(尤其大表新增字段时可能阻塞读写)
- 无法审计变更来源(谁改了结构体、何时生效、是否经过测试)
- 不同服务实例结构体版本不一致时,可能触发重复或冲突的字段添加
建议做法:仅在明确需要时手动触发,例如通过 CLI 命令或带开关的初始化逻辑:if os.Getenv("MIGRATE_ON_START") == "true" { db.AutoMigrate(...) }。
字段标签写错导致建表失败怎么办?
常见错误不是报错退出,而是静默忽略或建出不符合预期的表——比如忘记加 primaryKey,GORM 会默认用 ID uint 当主键,但若结构体里没定义 ID 字段,就可能建出无主键表;又或者 size:64 写成 size:64x,GORM 解析失败后直接跳过该约束,字段变成默认长度。
关键检查点:
-
gorm:"primaryKey"必须显式标注主键字段,且类型需匹配(如uint,int64) -
not null和default标签需配合数据库驱动支持(MySQL 中default:'abc'有效,但default:0可能被忽略) - 嵌入字段要用
embedded,否则 GORM 不展开子字段 - 字段名大小写敏感:结构体字段
Title对应数据库列title(小写),除非用column:title_zh显式指定
如何验证 AutoMigrate 实际执行了哪些 SQL?
靠日志,而不是靠猜。GORM 默认不打印 DDL 语句,必须显式开启 Logger 并设为 Info 或更高级别。
示例配置:
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: logger.Default.LogMode(logger.Info),
})
启动后,你会看到类似这样的输出:
ALTER TABLE `articles` ADD COLUMN `boss_id` varchar(64)
注意:AutoMigrate 的日志只在首次检测到差异时出现,后续相同结构不再重复打印。如果没看到 DDL 日志,说明没有实际变更,或 Logger 配置未生效。
真正容易被忽略的是:日志里不会告诉你“这个字段没加成功”,只会沉默跳过——所以每次改完结构体,必须查数据库确认字段真实存在,不能只信日志有没有输出。











