Go 路由模式

Go HTTP 路由机制,涵盖标准库 ServeMux(Go 1.22 增强)和第三方路由器(chi、gorilla/mux、echo)的模式匹配、路径参数与路由分组。

#type / concept #status / growing #tech / dev #resource / go

[!info] related notes

Go 路由模式

一句话定义

路由是将 HTTP 请求的方法 + 路径映射到对应处理函数的机制,Go 1.22 对标准库 ServeMux 做了重大增强,原生支持方法匹配和路径参数。

核心机制 / 工作原理

Go 1.22+ 增强的 ServeMux:

Go 1.22 引入了基于模式(pattern)的路由,支持 HTTP 方法和路径参数:

mux := http.NewServeMux()

// 方法匹配 + 路径参数
mux.HandleFunc("GET /users/{id}", getUser)
mux.HandleFunc("POST /users", createUser)
mux.HandleFunc("DELETE /users/{id}", deleteUser)

// {name} 匹配单个路径段,{name...} 匹配多段(通配符)
mux.HandleFunc("GET /files/{path...}", getFile)

在 Handler 中通过 r.PathValue() 提取参数:

func getUser(w http.ResponseWriter, r *http.Request) {
    id := r.PathValue("id") // 字符串类型,需手动转换
    fmt.Fprintf(w, "User: %s", id)
}

第三方路由器 chi:

chi 是最受欢迎的轻量路由器,提供路由分组、中间件挂载、嵌套路由等能力:

r := chi.NewRouter()
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)

r.Route("/api", func(r chi.Router) {
    r.Use(AuthMiddleware) // 仅对 /api 下的路由生效

    r.Route("/users", func(r chi.Router) {
        r.Get("/", listUsers)        // GET /api/users
        r.Post("/", createUser)      // POST /api/users
        r.Get("/{id}", getUser)      // GET /api/users/123
        r.Put("/{id}", updateUser)   // PUT /api/users/123
    })
})

// 参数提取
func getUser(w http.ResponseWriter, r *http.Request) {
    id := chi.URLParam(r, "id") // chi 专用的参数提取方式
}

gorilla/mux(已归档但仍广泛使用):

r := mux.NewRouter()
r.HandleFunc("/users/{id:[0-9]+}", getUser).Methods("GET")
r.HandleFunc("/users", createUser).Methods("POST")

// 正则约束:{id} 只匹配数字
// 查询参数:r.URL.Query().Get("page")

路由优先级与匹配规则:

标准库 ServeMux 的匹配规则:更具体的模式优先于更通用的模式。GET /users/{id}/users/{id} 更具体,后者匹配所有方法。/ 是最通用的模式,作为兜底。

最小例子 / 最小场景

// 用 Go 1.22 标准库构建 RESTful API
func main() {
    mux := http.NewServeMux()

    mux.HandleFunc("GET    /articles",          listArticles)
    mux.HandleFunc("POST   /articles",          createArticle)
    mux.HandleFunc("GET    /articles/{slug}",   getArticle)
    mux.HandleFunc("PUT    /articles/{slug}",   updateArticle)
    mux.HandleFunc("DELETE /articles/{slug}",   deleteArticle)
    mux.HandleFunc("GET    /articles/{slug}/comments", listComments)

    // 中间件包裹
    handler := LoggingMiddleware(CORSMiddleware(mux))

    log.Fatal(http.ListenAndServe(":8080", handler))
}

为什么重要

  • RESTful 设计:路由模式是构建 REST API 的骨架,清晰的路由映射让 API 自文档化。
  • Go 1.22 标准库够用:对大多数项目,增强后的 ServeMux 已能满足需求,不再强依赖第三方路由器。
  • 性能:路由匹配发生在每个请求上,高效的路由器(如 chi 基于基数树)能减少延迟。
  • 可维护性:路由分组和中间件挂载让大型 API 的组织结构清晰。

边界与易混淆点

  • Go 1.22 的路径参数 {name} 只匹配单个路径段(不含 /),{name...} 才匹配多段。注意不要在同一个模式中混用。
  • r.PathValue() 返回的是字符串,没有自动类型转换——与 chi 的 chi.URLParam() 行为一致。
  • chi、echo、gin 各自的路由语法略有差异(如正则约束、参数分隔符),迁移时需注意。
  • gorilla/mux 已于 2022 年归档(archived),新项目建议使用 chi 或标准库。
  • 查询参数(query string)不由路由器处理,需通过 r.URL.Query()r.URL.Query().Get() 手动解析。
  • 标准库 ServeMux 的尾部斜杠行为:/users/users/ 是不同的模式。默认会将 /users 重定向到 /users/(如果 /users/ 有注册)。
创建于 2026/6/25 更新于 2026/6/25