因为static.new()只匹配带前缀路径,而/favicon.ico是根路径请求,不匹配故404;需用app.static("/favicon.ico", "./public/favicon.ico")显式注册或自定义app.get()路由处理。

为什么 app.Use(static.New("./public")) 不处理 /favicon.ico
Fiber 的 static.New() 中间件默认只匹配带前缀的路径,比如 /assets/ 或 /images/。而浏览器发起的 favicon 请求是根路径下的 /favicon.ico,没有前缀,中间件根本不会尝试匹配它。即使你把 favicon.ico 放在 ./public/ 目录里,app.Use(static.New("./public")) 也完全无视这个请求——结果就是 404。
最简方案:用 app.Static() 单独注册 /favicon.ico
这是 Fiber 官方推荐、零额外依赖的做法,只需一行代码:
app.Static("/favicon.ico", "./public/favicon.ico")
- 路径必须写全:
"/favicon.ico"是请求路径,不能省略开头的/ - 文件路径要真实存在,比如
./public/favicon.ico;若放在项目根目录,就写./favicon.ico - 别写成
app.Use("/favicon.ico", static.New("./public"))—— 这会把整个./public挂到该前缀下,反而可能暴露不该公开的文件 - 该方式自动设置
Content-Type: image/x-icon和合理缓存头,不用手动干预
需要加日志或动态 fallback?改用 app.Get() 自定义 Handler
当你要记录访问、返回不同格式图标(如 .png)、或 fallback 到默认图标时,显式路由更可控:
app.Get("/favicon.ico", func(c *fiber.Ctx) error {
data, err := os.ReadFile("./public/favicon.ico")
if err != nil {
return c.Status(404).SendString("not found")
}
c.Type("image/x-icon")
c.Set("Cache-Control", "public, max-age=86400")
return c.Send(data)
})
- 务必检查
os.ReadFile()错误,否则空文件或权限问题会导致 panic -
c.Type("image/x-icon")不能省,否则 Chrome/Firefox 可能拒绝渲染 -
Cache-Control建议设为public, max-age=86400(24 小时),避免反复请求 - 如果同时支持
/apple-touch-icon.png,得单独再写一个app.Get()路由
前端 <link rel="icon"> 怎么配才不白忙
后端配好了,前端这行 HTML 写错照样不显示:
- 必须写
rel="icon",不是rel="shortcut icon"(后者是 IE 时代遗留) - 路径要和后端服务路径一致:如果后端用
app.Static("/favicon.ico", ...),前端就写href="/favicon.ico" - 别指望浏览器自动找根目录下的
favicon.ico—— 现代浏览器只在无<link>标签且 HTTP 响应无Link头时才 fallback 到根路径 - 改完立刻清缓存:Chrome 地址栏输
chrome://settings/clearBrowserData→ 勾选“缓存的图像和文件”
真正容易被忽略的是:Chrome 和 Safari 会分别发 /favicon.ico 和 /apple-touch-icon.png 两次请求,少配一个,iOS 设备上书签或桌面图标就空白。别只测标签页小图标就以为万事大吉。











