在Go语言构建的Web应用中,前端HTML文件能够正常渲染,但引用的CSS、JavaScript或图片资源却返回404错误——这几乎是每位开发者都会遇到的典型问题。其根本原因通常在于:静态文件的路由并未正确注册到主路由器上。
具体而言,许多初学者在代码中调用了 http.Handle(...),这个函数会将处理器注册到Go默认的 http.DefaultServeMux。然而,如果使用的是 *mux.Router,那么该路由器并没有接管这些静态路径,导致请求被错误地导向其他地方。
那么,正确的做法是什么呢?
所有静态资源路径都必须通过router(而非http.Handle)进行注册,以确保请求由同一路由实例统一分发。以下是一个推荐的结构化实现方案:
package main
import (
"fmt"
"log"
"net/http"
"github.com/gorilla/mux"
)
// ServeStatic 将指定目录下的子目录(如 scripts/、css/)统一挂载为带前缀的静态路由
func ServeStatic(router *mux.Router, staticRoot string) {
staticMappings := map[string]string{
"scripts": staticRoot + "/scripts/",
"css": staticRoot + "/css/",
"images": staticRoot + "/images/",
"fonts": staticRoot + "/fonts/",
}
for urlPrefix, fsPath := range staticMappings {
fullPath := "/" + urlPrefix + "/"
router.PathPrefix(fullPath).Handler(
http.StripPrefix(fullPath, http.FileServer(http.Dir(fsPath))),
).Methods("GET")
fmt.Printf("✅ Mounted %s → %s\n", fullPath, fsPath)
}
}
func main() {
router := mux.NewRouter() // 确保使用 mux.NewRouter() 初始化
// ✅ 关键:静态路由必须注册到 router,而非 http.DefaultServeMux
ServeStatic(router, "./static") // 所有静态文件放在 ./static/ 下
// 同时注册你的业务路由(如 /, /api/todo 等)
router.HandleFunc("/", homeHandler).Methods("GET")
log.Println("