buffalo框架本身不提供软删除功能,需开发者手动实现:添加*time.time类型的deletedat字段、用update替代delete、查询时显式添加deleted_at is null条件,并为该字段建立索引以保障性能。

Buffalo 框架本身不提供软删除功能,也没有内置的“恢复软删除数据”机制 —— 这是常见误解的根源。 它不像 Laravel 的 softDeletes 或 Django 的 is_active 字段那样默认支持标记删除。所谓“Buffalo 中恢复软删除”,实际是你自己实现的逻辑,恢复行为完全取决于你如何定义和查询“已删除”状态。
为什么 Buffalo 没有 soft_delete 方法?
Buffalo 是一个轻量级 Go Web 框架,专注路由、模板、中间件和数据库集成(通过 pop),但不封装业务语义。它不会自动添加 deleted_at 字段,也不会重写 Find 或 Destroy 行为来跳过被标记的记录。所有软删逻辑必须由开发者显式控制。
-
pop的Destroy默认执行的是真实 DELETE 语句(除非你手动改写为 UPDATE) - 没有
withTrashed()、onlyTrashed()这类查询修饰符 - 框架不拦截或重载模型方法 —— 你写的
SoftDelete()就只是个普通方法
如何手动实现可恢复的软删除?
你需要三要素:带时间戳的删除标记字段、UPDATE 替代 DELETE 的销毁逻辑、以及能查出“已标记但未物理删除”的查询方式。
Buffalo框架 1.0.1 版本源码包下载,适合需要错误处理改进、依赖更新、render.Download 注释和 request logger 调整的 v1 项目。
- 在模型结构体中添加字段:
DeletedAt time.Time `db:"deleted_at"` - 销毁时不用
tx.Destroy(model),改用:tx.Update(&model, "deleted_at", time.Now()) - 查询“有效数据”时加条件:
tx.Where("deleted_at IS NULL").All(&models) - 查询“已软删数据”时:
tx.Where("deleted_at IS NOT NULL").All(&models) - 恢复即清空标记:
tx.Update(&model, "deleted_at", nil)(注意传nil,不是time.Time{})
容易踩的坑:NULL vs 零值、索引与性能
Go 的 time.Time 零值是 0001-01-01 00:00:00 +0000 UTC,如果误存零值而非 NULL,会导致 WHERE 判断失效 —— 数据库里存的是合法时间,不是“未删除”状态。
- 务必使用指针类型
*time.Time,才能正确映射 SQL 的NULL - 字段定义应为:
DeletedAt *time.Time `db:"deleted_at"` - 建表时该字段需允许 NULL:
ALTER TABLE users ADD COLUMN deleted_at TIMESTAMP NULL - 若查询频繁涉及软删状态,建议对
deleted_at建索引,否则大表扫描会变慢
pop 查询时别漏掉软删条件
这是最常被忽略的一环:所有业务查询(列表、详情、关联加载)默认都不过滤 deleted_at。如果你没显式加 WHERE deleted_at IS NULL,就可能把已软删的数据暴露给前端或参与计算。
- 不要依赖“没人会删数据” —— 软删的意义在于可逆,前提是查询也守约
- 可以封装一个
ActiveOnly()方法返回pop.Query,复用条件逻辑 - 关联预加载(
Eager())同样不会自动过滤,必须手动在关联查询中补条件
真正关键的不是“怎么恢复”,而是“从一开始就把软删当成查询契约的一部分”——字段设计、销毁动作、查询条件、索引优化,四个环节缺一不可。一旦某处漏掉 WHERE deleted_at IS NULL,软删就形同虚设。










