Go 路由模式
Go HTTP 路由机制,涵盖标准库 ServeMux(Go 1.22 增强)和第三方路由器(chi、gorilla/mux、echo)的模式匹配、路径参数与路由分组。
#type / concept
#status / growing
#tech / dev
#resource / go
[!info] related notes
- 所属 MOC: Go Web 后端
- 前置概念: Go HTTP 中间件
- 并列概念: Go gRPC
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/有注册)。