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

如何使用http.ServeMux实现路由分组?

问题原因

你遇到的404错误,核心是ServeMux的路径匹配规则和路由转发逻辑没处理对:

  • 当你用apiMux.Handle("/my-group", group)时,只有请求路径完全等于/my-group的请求才会被转发给子ServeMux;
  • 即使把挂载路径改成/my-group/,子ServeMux会收到完整的请求路径(比如/my-group/foo),但你子路由注册的是/foo,自然匹配不上。
正确实现方式

方式一:用http.StripPrefix剥离前缀(推荐)

这种方式能真正实现路由分组,统一管理前缀,子路由只需写相对路径:

import "net/http"

func GetAPI() *http.ServeMux {
    apiMux := http.NewServeMux()

    group := http.NewServeMux()
    // 子路由写相对路径
    group.HandleFunc("/foo", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        w.Write([]byte("Success from /my-group/foo"))
    })
    // 剥离"/my-group/"前缀后,将剩余路径传给子ServeMux
    apiMux.Handle("/my-group/", http.StripPrefix("/my-group/", group))

    // 其他全局路由示例
    apiMux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        w.Write([]byte("Healthy"))
    })

    return apiMux
}

此时访问http://localhost:8080/my-group/foo就能正常匹配到子路由。

方式二:子路由统一带前缀(不推荐,维护性差)

如果不想用StripPrefix,可以给子路由直接加上分组前缀,再挂载到父ServeMux:

import "net/http"

func GetAPI() *http.ServeMux {
    apiMux := http.NewServeMux()

    group := http.NewServeMux()
    // 子路由直接写完整分组路径
    group.HandleFunc("/my-group/foo", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        w.Write([]byte("Success from /my-group/foo"))
    })
    apiMux.Handle("/", group)

    // 其他全局路由
    apiMux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        w.Write([]byte("Healthy"))
    })

    return apiMux
}
关键规则提醒
  • ServeMux挂载路径如果以/结尾,会匹配所有以此路径开头的请求;否则仅匹配完全相等的路径。
  • 子ServeMux默认会收到完整请求路径,必须用StripPrefix剥离前缀,才能让子路由匹配相对路径。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 14:02:36