:id匹配单段非斜杠路径参数(如/user/123→id="123"),*path匹配剩余全部路径(如/static/js/app.js→path="/js/app.js");二者均为第三方路由库特性,标准net/http不支持。
:id 和 *path 的区别必须分清Go 标准库 net/http 本身不支持路径参数解析,:id 这种写法只在第三方路由库(如 gorilla/mux、chi)中有效。标准 http.ServeMux 只做前缀匹配,无法提取 /user/123 中的 123。
常见错误是以为 http.HandleFunc("/user/:id", handler) 能自动解析 :id —— 实际会直接匹配字面量 "/user/:id" 这个路径,导致 404。
:id 是命名参数:匹配单段非斜杠内容,例如 /user/123 → id="123"
*path 是通配参数:匹配剩余全部路径,例如 /static/js/app.js → path="/js/app.js"
:param 不能连续,/a/:x/:y 合法,/a/:x:b 非法gorilla/mux 提取 :id 时别漏掉 Vars() 调用gorilla/mux 把参数存在 http.Request 的上下文里,必须显式调用 mux.Vars(r) 才能拿到 map。直接读 r.URL.Path 拿不到解析结果。
import "github.com/gorilla/mux"
func handler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r) // 必须这一步
id := vars["id"] // 类型是 string
if id == "" {
http.Error(w, "missing id", http.StatusBadRequest)
return
}
// id 是字符串,需手动转 int 等类型
userID, err := strconv.Atoi(id)
if err != nil {
http.Error(w, "invalid id", http.StatusBadRequest)
return
}
}
mux.Vars(r) 返回 map[string]string,不存在的 key 返回空字符串,不是 panicrouter.HandleFunc("/user/{ID}", h).Methods("GET") 对应 vars["ID"],不是 vars["id"]
{id:[0-9]+} 正则约束,mux
Vars() 拿到的一定是符合规则的值chi 的 URLParam() 更轻量,但注意它不校验路径段是否为空chi 不依赖上下文,直接从 *http.Request 解析,用 chi.URLParam(r, "id") 即可。但它不会像 mux 那样在路由注册时做正则预检,空段(如 /user//post)也会返回空字符串。
import "github.com/go-chi/chi/v5"
func handler(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id") // 不需要先调 Vars()
if id == "" {
http.Error(w, "id required", http.StatusBadRequest)
return
}
// 注意:这里 id 可能是 "/" 开头的路径(如果路由是 /files/*path)
// 用 chi.URLParam(r, "*path") 获取通配部分
}
chi.URLParam(r, "*path") 返回的是完整匹配段,包括开头的 /,比如 /a/b/c → "/a/b/c"
POST /user/{id}/avatar,而请求是 POST /user//avatar,chi 仍会返回空字符串,需业务层额外判空chi 的中间件链中,URLParam 始终可用,不依赖中间件顺序;但 mux 的 Vars() 必须在路由匹配之后调用(即必须在 handler 内)如果不用路由库、自己切 r.URL.Path,必须先 url.PathUnescape,否则 %2F 会被当普通字符;同时要防 ../ 路径穿越。
path.Clean(r.URL.Path) 归一化路径,再按 / 切分strings.Split(r.URL.Path, "/") —— //user/123 会多出空段match, _ := regexp.MatchString(`^\d+$`, id),而不是只信路由定义动态参数本质是信任边界——路由库帮你做了第一层路径结构校验,但业务逻辑仍要独立验证内容合法性。这点容易被忽略,尤其在快速原型阶段。