Go使用gorilla/mux时http.HandleFunc注册路由未触发如何解决
你的代码存在两个核心问题,直接导致路由handler不执行:
1. 路由注册对象不匹配
你在循环中使用http.HandleFunc()注册的路由,是绑定到Go标准库默认的全局路由实例上的,但你启动服务时http.ListenAndServe()的第二个参数传入的是自己新建的mux.Router实例,相当于所有注册的页面路由完全没有生效,所有请求只会走你给router配置的静态文件兜底逻辑,所以才会返回静态资源的目录列表。
2. 循环闭包变量捕获错误
就算把路由注册到正确的mux.Router实例上,你当前的handler写法也会出现逻辑错误:for循环里的page变量是同一块内存地址,每次迭代只是更新该地址存储的值,直接在闭包里引用page的话,所有handler最终捕获到的都会是循环结束时最后一个page的值,无法对应每个路径预期的page数据。
修正后的代码
func main() { defer func() { if r := recover(); r != nil { fmt.Printf("Recovering from panic, error is: %v \n", r) } }() router := mux.NewRouter() router.Use(middlewareHeaders) // 提前解析模板,保证handler执行时能拿到正确的模板实例 var err error tmpl, err = template.ParseGlob("views/*") if err != nil { panic(err.Error()) } for _, page := range pages.Pages { fmt.Print("page: ") fmt.Println(page.Slug) // 定义局部变量捕获当前迭代的page,解决闭包变量共享问题 currentPage := page // 将路由注册到实际使用的mux.Router实例上 router.HandleFunc(currentPage.Slug, func(w http.ResponseWriter, r *http.Request) { fmt.Println("http.HandleFunc") err := tmpl.ExecuteTemplate(w, currentPage.Template, currentPage) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } }) } router.PathPrefix("/").HandlerFunc(func(res http.ResponseWriter, req *http.Request) { http.FileServer(http.Dir("./static/")).ServeHTTP(res, req) }) fmt.Println("Server running on localhost" + pages.Config.Port) err = http.ListenAndServe(pages.Config.Port, handlers.CompressHandler(router)) if err != nil { log.Fatal(err) } }
内容的提问来源于stack exchange,提问作者pigfox
相关产品推荐
相关产品推荐

