You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GORM中db.FirstOrCreate与db.Where().FirstOrCreate的差异解析

关于GORM中FirstOrCreate两种写法的差异解析

嗨,我来帮你把这两种写法的区别讲明白,核心就在于查询条件和创建时赋值的逻辑划分不同:

1. db.FirstOrCreate(&user, User{Name: "non_existing"})

这种写法里,第二个传入的结构体参数承担了两个角色:

  • 首先作为查询匹配条件:GORM会用这个结构体里的非零字段(这里是Name)去数据库查找匹配的记录
  • 其次作为创建时的属性模板:如果数据库里找不到匹配的记录,GORM会直接用这个结构体的字段值来插入一条新记录

举你的例子:

未找到记录的情况:db.FirstOrCreate(&user, User{Name: "non_existing"})
执行INSERT INTO "users" (name) VALUES ("non_existing");,最终user会被赋值为新创建的这条记录(包含自增ID和Name字段)

如果此时数据库里已经有一条Name="non_existing"的记录,GORM会直接把这条记录查询出来赋值给user,不会执行插入操作。

2. db.Where(User{Name: "Jinzhu"}).FirstOrCreate(&user)

这种写法把查询条件和创建赋值做了分离:

  • Where(User{Name: "Jinzhu"})里的内容仅仅是查询条件,GORM只会用它来查找匹配的记录
  • 当找不到匹配记录时,GORM会创建一个默认的空结构体实例(只有主键等自增字段会被数据库自动填充,其他字段会用零值,比如Name会是空字符串,除非数据库字段有默认值),而不会把Where里的条件作为创建时的属性值

举个补充例子:如果执行db.Where(User{Name: "NewUser"}).FirstOrCreate(&user)且数据库里没有这条记录,最终插入的记录Name字段会是空(或者数据库默认值),而不是"NewUser"。

额外补充:如果想让Where条件同时作为创建赋值

如果想用Where的条件作为创建时的属性,需要结合Attrs()方法:

db.Where(User{Name: "Jinzhu"}).Attrs(User{Name: "Jinzhu"}).FirstOrCreate(&user)

或者用Assign()(区别是Assign()不管有没有找到记录,都会把属性赋值给user,而Attrs()只有在创建新记录时才会赋值)。


内容的提问来源于stack exchange,提问作者Asnim P Ansari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 22:57:39