First查不到记录时返回gorm.ErrRecordNotFound错误而非nil,需用errors.Is(err, gorm.ErrRecordNotFound)显式判断;传参必须为单结构体地址,且应配合Order明确排序意图。

First查不到记录时返回什么
默认情况下,First查不到数据会返回 gorm.ErrRecordNotFound 错误,而不是 nil。很多人直接判 err == nil 就认为查到了,结果后续对空结构体字段取值 panic。
- 必须显式检查错误类型:
errors.Is(err, gorm.ErrRecordNotFound) - 如果只关心是否存在,用
Limit(1).Select("id").Find(&id)避免全字段加载 -
First默认按主键升序取第一条,不加Order时行为依赖表结构,别假设“最新一条”
Find和First在切片/指针上的区别
Find 要求传入切片地址(如 &users),First 要求传入单个结构体地址(如 &user)。传错类型不会编译报错,但运行时 GORM 会静默失败或填充错误内存。
-
Find(&users)→ 正确:users 是[]User类型 -
Find(users)或Find(&user)→ 错误:GORM 不报错,但users为空或内容混乱 -
First(&user)→ 正确:user 是User类型 -
First(&users)→ 错误:可能 panic 或写坏内存
Where条件后跟 First 和 Find 的行为差异
两者都支持链式调用 Where,但底层 SQL 生成逻辑一致,区别只在结果处理方式——First 加了 LIMIT 1,Find 没加。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 性能上,
First在命中第一条后就停止扫描,大数据量时更省;Find会拉全量再截断(除非你手动Limit(1)) - 如果 WHERE 条件可能匹配多条,又只想取一条,优先用
First+Order明确意图,比如Order("created_at DESC").First(&user) - 注意:MySQL 8.0+ 对
LIMIT+ORDER BY有索引优化要求,没建好索引时First未必比Find快
软删除场景下 First 可能“漏掉”有效记录
开启软删除(即模型含 DeletedAt 字段)后,GORM 默认自动过滤已软删记录。但如果你手动写了 Where("deleted_at IS NULL"),又同时用了软删除,会导致条件重复或冲突。
立即学习“go语言免费学习笔记(深入)”;
- 确认是否启用了软删除:
db.Unscoped().First(&user)可查到软删记录 - 想查“未软删且满足其他条件”的记录,别再手动加
Where("deleted_at IS NULL"),GORM 已内置处理 - 如果模型没定义
DeletedAt却用了Unscoped(),GORM 会忽略它,不报错也不生效
& 符号,或者忘了处理 ErrRecordNotFound,后面读字段就崩了。

















