升级 GORM 到 2.0 至少要改 5 个地方,下面按“必须改”和“建议改”两类列出,并给出最小可编译的示例,照着替换即可通过编译。
---
一、必须改的 5 处(不编译不过)
序号 老 1.x 写法 2.0 新写法 备注
1 import "github.com/jinzhu/gorm" import "gorm.io/gorm" 主库路径全变
2 import _ "github.com/jinzhu/gorm/dialects/mysql" import "gorm.io/driver/mysql" 驱动也独立
3 db, err := gorm.Open("mysql", dsn) db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) 参数顺序/类型全变
4 if db.RecordNotFound() { … } if errors.Is(result.Error, gorm.ErrRecordNotFound) { … } 方法被移除
5 钩子函数签名任意 必须统一为 func(*gorm.DB) error 否则钩子不会生效
最小可编译启动示例(MySQL):
package main
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type User struct {
ID uint
Name string
}
func main() {
dsn := "user:pass@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic(err)
}
db.AutoMigrate(&User{})
}
---
二、建议继续改的 4 处(功能/性能更好)
老 1.x 习惯 2.0 推荐做法 原因
db.Find(&u).Update(&u) db.Model(&User{}).Where("id=?", id).Updates(map[string]interface{}{"name": "tom"}) 结构体更新默认忽略零值
全局更新无保护 默认禁止,需要 gorm.Config{AllowGlobalUpdate: true} 防止误伤全表
并发链式调用 使用 db.WithContext(ctx).Session(&gorm.Session{}) 2.0 共享 Statement,必须 Session 隔离
零值条件被忽略 用 map 或 Select("age") 强制更新 结构体查询/更新会跳过零值字段
---
三、全局钩子升级示例(可选)
若原来在 1.x 里用 BeforeSave,2.0 可以注册一次即可作用于全部模型:
db.Callback().Create().Before("gorm:before_create").
Register("global:before_create", func(tx *gorm.DB) error {
now := time.Now()
tx.Statement.SetColumn("CreatedAt", now)
return nil
})
---
四、一键检查清单
1. 全文搜索 github.com/jinzhu/gorm → 替换为 gorm.io/gorm
2. 全文搜索 gorm.Open("mysql" → 替换为 gorm.Open(mysql.Open(dsn), &gorm.Config{})
3. 全文搜索 .RecordNotFound() → 替换为 errors.Is(err, gorm.ErrRecordNotFound)
4. 所有钩子函数加上 func(*gorm.DB) error 签名
5. 重新 go mod tidy 拉取新依赖
完成以上 5 步即可通过编译;再继续把“建议改”的 4 处处理完,就真正享受 2.0 的全部新特性。祝升级顺利!