Fiber没有内置路由级缓存中间件,所谓“内置”是误传;fiber/middleware/cache是需手动安装的社区包,按路径前缀批量缓存、不区分查询参数、内存压力大,不适合单接口精细控制。

Fiber 没有内置的「路由级缓存中间件」,所谓“内置缓存”是误传——你看到的 fiber/middleware/cache 是社区维护的独立包,不是框架自带功能,且它默认缓存响应体到内存,不适合单接口精细控制。
为什么 fiber/middleware/cache 不算“内置”,也不推荐用于单路由
这个包需要显式 go get github.com/gofiber/fiber/v2/middleware/cache 安装,v3 版本甚至已移出主仓库;它按路径前缀(如 /api/)批量缓存,无法区分 /posts?lang=zh 和 /posts?lang=en;更关键的是,它把整个 ctx.Response().Body() 拷贝进内存 map,高并发返回大 JSON 时 GC 压力陡增,反而拖慢 TTFB。
- 它不读取请求 query 参数做 key 分离,缓存易错版本
- 缓存失效只能靠 TTL,没法对接 DB 的
updated_at动态刷新 - 若你只希望浏览器或 CDN 缓存 60 秒,它却在服务端多存一份,纯属冗余
真正轻量有效的“缓存”就是手动设 Cache-Control
对内容稳定、更新低频的接口(如健康检查、公开文章列表),直接在 handler 开头调 c.Set("Cache-Control", ...),比任何中间件都快、可控、零内存开销。
-
public, max-age=60:允许 CDN、代理、浏览器共同缓存 60 秒 -
private, max-age=300:仅终端浏览器可缓存,适合用户私有数据 -
no-store:禁止任何缓存,含敏感字段或实时性要求高的接口必须用 - 必须在
c.JSON()、c.SendString()等任何写响应操作之前调用,否则 header 已发送,设置无效
动态缓存时间怎么算?别硬编码 max-age
当缓存策略依赖后端状态(如文章最后更新时间),max-age 应从数据源实时计算,而非写死数字。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
立即学习“go语言免费学习笔记(深入)”;
- 从 DB 查出
item.UpdatedAt,用int(time.Since(item.UpdatedAt).Seconds())得出距今秒数 - 取最小值:
min(age, 3600),避免缓存时间超过业务容忍上限 - 若
age (1 分钟内更新过),直接设 <code>no-store,防止脏缓存 - 注意:Fiber 不自动处理 ETag 校验,要强一致性就得自己生成 + 手动比对
c.Get("If-None-Match")
StrictRouting 和尾斜杠会悄悄破坏缓存逻辑
缓存是否生效,取决于请求路径是否稳定。而 Fiber 默认 StrictRouting: true,会让 /article/123 和 /article/123/ 被视为两个路由——前者命中缓存逻辑,后者直接 404,根本进不了 handler。
- 别关
StrictRouting: false,否则可能让/users错误匹配/users/123 - 正确做法:显式注册两种路径,或加一层重定向中间件,统一跳转到无尾斜杠版本
- 所有缓存相关逻辑(包括 ETag 生成)都必须放在能稳定执行的 handler 内,路径不一致就全白搭
真正影响缓存效果的,从来不是有没有中间件,而是路径是否收敛、header 是否及时设置、max-age 是否贴合数据时效——这些细节一旦漏掉,再“高级”的缓存方案也形同虚设。


















