一个 GORM 的常见问题。GORM 的Save方法在更新时会忽略零值zero values导致非空字段如0、、false无法被保存到数据库。问题根源go复制type User struct { ID uint Name string Age int Admin bool } // 假设数据库中 Age25, Admintrue user : User{ID: 1, Name: 张三, Age: 0, Admin: false} db.Save(user) // 结果Age 和 Admin 不会被更新为 0 和 falseGORM 默认使用Update策略会跳过零值字段以防止误更新。解决方案方案 1使用Select明确指定更新字段推荐go复制// 明确告诉 GORM 要更新哪些字段包括零值 db.Select(name, age, admin).Save(user) // 或更新所有字段 db.Select(*).Save(user)方案 2使用Map更新go复制db.Model(User{}).Where(id ?, 1).Updates(map[string]interface{}{ name: 张三, age: 0, // 零值会被更新 admin: false, // 零值会被更新 })方案 3使用指针或sql.Null*类型go复制type User struct { Age *int // 使用指针 Admin sql.NullBool // 或使用 sql.Null 类型 } age : 0 admin : false user : User{ID: 1, Age: age, Admin: sql.NullBool{Bool: admin, Valid: true}} db.Save(user)方案 4全局配置CreateBatchSizeGORM v2go复制// 在连接配置中设置 db, err : gorm.Open(mysql.Open(dsn), gorm.Config{ CreateBatchSize: 1000, }) // 或使用 Session db.Session(gorm.Session{FullSaveAssociations: true}).Save(user)方案 5使用UpdateColumn绕过 Hook 和零值检查go复制db.Model(user).UpdateColumn(age, 0)最佳实践建议表格场景推荐方案明确知道要更新哪些字段Select(field1, field2).Save()动态更新字段不固定Updates(map[string]interface{}{})字段可能为零值且是常规操作使用指针类型*int,*string批量更新不在乎 HookUpdateColumn完整示例go复制package main import ( gorm.io/driver/mysql gorm.io/gorm ) type Product struct { ID uint Name string Price int Stock int } func main() { dsn : user:passtcp(127.0.0.1:3306)/dbname?charsetutf8mb4parseTimeTruelocLocal db, _ : gorm.Open(mysql.Open(dsn), gorm.Config{}) // 方法1Select 明确指定 product : Product{ID: 1, Name: iPhone, Price: 0, Stock: 0} db.Select(name, price, stock).Save(product) // 方法2Map 更新更灵活 db.Model(Product{}).Where(id ?, 1).Updates(map[string]interface{}{ price: 0, stock: 0, }) }核心要点GORM 的Save默认是智能更新要强制更新零值必须用Select或Map方式显式声明。