You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go 1.22新高级路由下GET /users/register处理器无法访问的问题

问题分析:Go 1.22中访问GET "/users/register"返回404的原因及解决办法

你在试用Go 1.22新特性时,访问GET "/users/register"始终返回404,无法触发对应的处理器函数。相关代码如下:

主包代码

func main() {
    if err := godotenv.Load(); err != nil {
        log.Fatal("Failed to load .env:", err)
    }

    _, err := repository.InitDB()
    if err != nil {
        log.Fatal("Failed to initialise the database:", err)
    }

    userMux := http.NewServeMux()
    if err := handlers.InitUserRoutes(userMux); err != nil {
        log.Fatal("Failed to initialise user routes:", err)
    }

    mux := http.NewServeMux()
    mux.Handle("/users/", userMux)
    log.Fatal(http.ListenAndServe(fmt.Sprintf("%s:%s", os.Getenv("DOMAIN"), os.Getenv("PORT")), mux))
}

handlers包代码

var templates *template.Template

func InitUserRoutes(mux *http.ServeMux) error {
    var err error
    templates, err = utils.ParseTemplates("web/templates/user")
    if err != nil {
        return err
    }

    mux.HandleFunc("GET /register/", registerGet)
    mux.HandleFunc("POST /register/", registerPost)

    return nil
}

func registerGet(w http.ResponseWriter, r *http.Request) {
    fmt.Println("I'm here")
    err := templates.ExecuteTemplate(w, "register.html", nil)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

func registerPost(w http.ResponseWriter, r *http.Request) {
    if err := r.ParseForm(); err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    fmt.Printf("%#v\n\n%#v", r.Form, r.PostForm)
    email, username, password := r.FormValue("email"), r.FormValue("username"), r.FormValue("password")
    fmt.Printf("%v, %v, %v\n", email, username, password)
}

utils包代码

func ParseTemplates(folderPath string) (*template.Template, error) {
    return template.ParseGlob(filepath.Join(folderPath, "*.html"))
}

问题根源

问题出在路由路径的尾斜杠匹配不一致:

  1. 主ServeMux将"/users/"路径挂载到userMux,当请求"/users/register"时,userMux接收到的路径是去掉前缀后的"/register"。
  2. 但你在userMux中注册的路由是"GET /register/"(带尾斜杠),和实际传入的"/register"(不带尾斜杠)不匹配,因此返回404。

Go 1.22的ServeMux在子路由挂载场景下,不会自动将不带尾斜杠的路径重定向到带尾斜杠的版本,也不会模糊匹配尾斜杠。

解决办法

有两种简单的修复方式:

  • 方式一:修改子路由的路径,去掉尾斜杠
    将handlers包中的路由注册代码改为:

    mux.HandleFunc("GET /register", registerGet)
    mux.HandleFunc("POST /register", registerPost)
    

    这样userMux就能匹配到"/register"路径,对应请求"/users/register"即可触发处理器。

  • 方式二:调整主路由的挂载路径(可选)
    如果你希望保留子路由的尾斜杠,可以将主ServeMux的挂载路径改为"/users"(不带尾斜杠),同时让用户访问"/users/register/"(带尾斜杠)。但这种方式需要前端请求路径同步修改,不如方式一灵活。

内容的提问来源于stack exchange,提问作者Recovery Email

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 14:30:55