http.fileserver 直接用会 404,因相对路径依赖启动目录、目录不存在或不可读时不报错而静默失败;需用 filepath.abs 转绝对路径、os.stat 预检、filepath.join 处理分隔符;默认不支持 index.html 自动展示,需手动兜底或中间件处理;防路径遍历须用 filepath.clean 校验前缀;生产环境缺乏缓存、gzip、range 等支持,建议用 cdn 或 nginx。

为什么 http.FileServer 直接用会 404?
常见错误是直接传入相对路径,比如 http.FileServer(http.Dir("assets")),但当前工作目录不一定是项目根目录——启动位置变了,assets 就找不到了。更隐蔽的是,http.Dir 要求路径必须存在且可读,否则不会报错,但所有请求都返回 404。
- 用
filepath.Abs转成绝对路径,避免工作目录干扰 - 启动前先
os.Stat检查目录是否存在,否则早暴露问题 - Windows 下注意路径分隔符,
filepath.Join比硬写"assets\css"更安全
如何让 http.FileServer 支持 index.html 自动展示?
http.FileServer 默认不处理目录索引,访问 / 或 /docs/ 会直接 404,除非显式请求 /index.html。这不是 bug,是设计使然:它只做静态文件映射,不带路由逻辑。
- 用
http.ServeFile单独兜底根路径:if r.URL.Path == "/" { http.ServeFile(w, r, "index.html"); return } - 或者用
http.StripPrefix+http.FileServer组合,再加一层中间件判断后缀是否为空、是否为目录 - 别依赖
http.Dir的隐式行为——它不会自动找index.html,连日志都不会打
怎么限制只能访问子目录,防止路径遍历(../)?
http.FileServer 内部已做基础过滤,对 ../ 会返回 400,但前提是路径没被提前拼接过。一旦你手动用 filepath.Join 拼出路径再传给 http.Dir,就可能绕过校验。
- 永远把用户输入的路径交给
http.FileServer前,先用filepath.Clean归一化 - 检查清理后路径是否仍以允许的根目录开头,例如
strings.HasPrefix(cleaned, allowedRoot) - 不要自己拼路径再 open,那是给自己挖坑——
http.FileServer的安全机制只在它自己解析 URL 时生效
为什么生产环境不建议直接用 http.FileServer?
它没缓存头、不支持 gzip、不处理 If-Modified-Since、不支持 range 请求(视频/大文件断点续传失效),而且日志粒度粗,出问题只能靠 net/http/pprof 手动抓。
立即学习“go语言免费学习笔记(深入)”;
- 开发阶段够用,但上线前至少加一层
gziphandler(第三方库)或自己 wrapResponseWriter - 静态资源建议走 CDN,后端只留 API;真要自托管,优先考虑 Caddy/Nginx,不是因为 Go 不行,而是重复造轮子成本高
- 如果非要用 Go 托管,记得设置
w.Header().Set("Cache-Control", "public, max-age=3600"),不然浏览器每次重拉
真正难的不是起服务,是搞清哪些边界它不管、哪些安全假设它依赖、哪些 HTTP 特性它故意省略——这些地方不填平,线上跑几天就会冒出奇怪的 404 或慢响应。










