编程 GORM v1.30 的 gorm.G[T]:泛型 API 与链式 API 并存,复用实例不再污染 SQL

2026-10-05 00:04:54

GORM v1.30 的 gorm.G[T]:泛型 API 与链式 API 并存,复用实例不再污染 SQL

GORM 从 v1.30.0 起正式支持 Go Generics,入口是 gorm.G[T]。传统链式 API 保持完全向后兼容,两套写法可以混用。泛型 API 要解决两件事:减少复用 gorm.DB 实例导致的 SQL 条件污染,以及提升类型安全。为了避免误用,泛型版有意移除了 FirstOrCreate 和 Save。官方也在设计 gorm CLI 工具,做更强的代码生成。

func G[T any](db *DB, opts ...clause.Expression) Interface[T]

CRUD 写法

ctx := context.Background()

gorm.G[User](db).Create(ctx, &User{Name: "Alice"})
gorm.G[User](db).CreateInBatches(ctx, users, 10)

user, err := gorm.G[User](db).Where("name = ?", "Jinzhu").First(ctx)
users, err := gorm.G[User](db).Where("age  ?", 14)
return nil
}).Find(ctx)

users, err = gorm.G[User](db).
Preload("Friends", func(db gorm.PreloadBuilder) error {
db.Select("id", "name").Order("age desc")
return nil
}).
Preload("Friends.Pets", func(db gorm.PreloadBuilder) error {
db.LimitPerRecord(2)
return nil
}).Find(ctx)

LimitPerRecord(2) 为每条主记录限制预加载的关联数量。many2many 关联不支持 LimitPerRecord。

Raw 与 gen 代码生成

Raw 仍然保留:

gorm.G[User](db).Raw("SELECT * FROM users WHERE name = ? AND age > ?", "jinzhu", 18).Find(ctx)

需要类型安全的原生查询时,官方推荐用代码生成工具:定义 Go interface,用注释写模板 SQL,生成后按下面的方式调用。

query.Query[User](db).GetByID(ctx, 10)

Gen 文档:

为什么复用同一个泛型实例不会条件污染

传统写法里复用 *gorm.DB 容易把上一次的条件带进下一次查询。泛型 API 在机制上规避了这一点:apply(ctx) 内部会先执行

db = db.Session(&Session{NewDB: true, Context: ctx}).getInstance()

然后重放保存的 ops。也就是说,每次操作方法都从一个干净实例开始,条件不会累积:

genericDB := gorm.G[User](db).Where("name = ?", "jinzhu")
user1, err1 := genericDB.Where("age > ?", 10).First(ctx)
user2, err2 := genericDB.Where("age > ?", 20).First(ctx)

第二次查询不会带上第一次的 age > 10。此外,context 直接传给每个操作方法,错误也从操作方法直接返回,不需要 db.WithContext(ctx) 再加 db.Error 两步。

Set:Set-based 写操作

Set(assignments ...clause.Assigner)

v1.30.4 起,Generics API 支持 Set-based Create/Update;v1.31.0 起,Set API 支持关联操作,并启用了条件批量关联更新。

版本与项目信息

  • v1.30.0(2025-05-25):Implement Generics API (#7424)
  • v1.30.2:新增 DefaultContextTimeout 选项 (#7567)、slog 集成
  • v1.30.4:Add Set-based Create and Update support to Generics API (#7578)
  • v1.31.0:Add association operation support to generics Set API and enable conditional bulk association updates (#7581)
  • 当前最新版本:v1.31.2

仓库:(约 40k stars,MIT,模块路径 gorm.io/gorm)

文档:

被移除方法的迁移

  • Save → 新建用 Create,更新用 Updates
  • FirstOrCreate → 先 First 查询,没有再 Create;或使用 clause.OnConflict{Columns: ..., DoUpdates: ...} 做 Upsert
复制全文 生成海报 GORM框架 Go ORM Go语言 数据库

推荐文章

程序员茄子在线接单