如何在Go中获取请求对应的原始注册路由URL?
Go语言获取注册的原始路由(对应Flask的request.url_rule.rule)
在Go中要实现类似Flask里获取原始注册路由的功能,分两种常见场景处理:
一、使用gorilla/mux路由库(推荐)
gorilla/mux是Go生态中最常用的Web路由库,支持路由参数、子路由(类似Flask的Blueprint),并且原生提供了获取原始路由模板的方法。
步骤1:安装依赖
go get github.com/gorilla/mux
步骤2:代码实现
package main import ( "fmt" "net/http" "github.com/gorilla/mux" ) func userHandler(w http.ResponseWriter, r *http.Request) { // 获取当前匹配的路由对象 currentRoute := mux.CurrentRoute(r) if currentRoute != nil { // 读取注册时的原始路由模板 rawRoute, err := currentRoute.GetPathTemplate() if err == nil { fmt.Fprintf(w, "原始路由: %s\n", rawRoute) // 当请求http://localhost:8080/v1/user/001时,会输出:/v1/user/{user_id} } else { fmt.Fprintf(w, "获取路由模板失败: %v\n", err) } } else { // 未匹配到预定义路由时,返回请求路径 fmt.Fprintf(w, "请求路径: %s\n", r.URL.Path) } } func main() { // 创建根路由 rootRouter := mux.NewRouter() // 创建子路由(对应Flask的Blueprint) v1Router := rootRouter.PathPrefix("/v1").Subrouter() // 注册带参数的路由 v1Router.HandleFunc("/user/{user_id}", userHandler).Methods("GET") fmt.Println("服务器运行在 :8080") http.ListenAndServe(":8080", rootRouter) }
说明
mux.CurrentRoute(r):获取当前请求匹配到的路由实例GetPathTemplate():返回注册时的原始路由模板,比如/v1/user/{user_id},和Flask里的<user_id>占位符对应
二、使用标准库net/http
Go标准库的net/http本身没有内置路由参数解析和原始路由存储的功能,需要自己封装路由逻辑来实现:
代码实现
package main import ( "context" "fmt" "net/http" "regexp" ) // 自定义路由结构体,存储原始模板、正则匹配规则和处理函数 type Route struct { Pattern string Handler http.HandlerFunc regex *regexp.Regexp } // 自定义Router管理所有路由 type Router struct { routes []Route } func NewRouter() *Router { return &Router{} } // 注册路由:将占位符{param}转换为正则捕获组,同时保存原始模板 func (r *Router) HandleFunc(pattern string, handler http.HandlerFunc) { // 替换{param}为正则匹配规则,匹配非/的任意字符 rePattern := regexp.MustCompile(`\{([^}]+)\}`).ReplaceAllString(pattern, `([^/]+)`) r.routes = append(r.routes, Route{ Pattern: pattern, Handler: handler, regex: regexp.MustCompile("^" + rePattern + "$"), }) } // 实现http.Handler接口,处理路由匹配 func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { path := req.URL.Path for _, route := range r.routes { if route.regex.MatchString(path) { // 将原始路由模板存入请求上下文,供handler读取 ctx := context.WithValue(req.Context(), "raw_route", route.Pattern) route.Handler(w, req.WithContext(ctx)) return } } // 未匹配到路由,返回404 http.NotFound(w, req) } func userHandler(w http.ResponseWriter, r *http.Request) { // 从上下文读取原始路由模板 rawRoute, ok := r.Context().Value("raw_route").(string) if ok { fmt.Fprintf(w, "原始路由: %s\n", rawRoute) // 请求http://localhost:8080/v1/user/001时,输出:/v1/user/{user_id} } else { fmt.Fprintf(w, "请求路径: %s\n", r.URL.Path) } } func main() { router := NewRouter() router.HandleFunc("/v1/user/{user_id}", userHandler) fmt.Println("服务器运行在 :8080") http.ListenAndServe(":8080", router) }
说明
- 自定义
Router结构体管理所有路由,注册时保存原始模板和对应的正则规则 - 匹配路由时,将原始模板存入请求上下文
context,在handler中通过上下文获取
内容的提问来源于stack exchange,提问作者romlym
相关产品推荐
相关产品推荐

