在Go(语言)中注册处理程序时,有没有办法在模式中指定通配符?
例如:
http.HandleFunc("/groups/*/people", peopleInGroupHandler)
Run Code Online (Sandbox Code Playgroud)
其中*
可以是任何有效的URL字符串.或者是唯一的解决方案匹配/groups
并从handler(peopleInGroupHandler
)func中计算出其余部分?
Eva*_*haw 87
http.Handler和http.HandleFunc的模式不是正则表达式或整数.没有办法指定通配符.他们在这里记录.
也就是说,创建自己的处理程序并不难,可以使用正则表达式或任何其他类型的模式.这是一个使用正则表达式(已编译但未经过测试):
type route struct {
pattern *regexp.Regexp
handler http.Handler
}
type RegexpHandler struct {
routes []*route
}
func (h *RegexpHandler) Handler(pattern *regexp.Regexp, handler http.Handler) {
h.routes = append(h.routes, &route{pattern, handler})
}
func (h *RegexpHandler) HandleFunc(pattern *regexp.Regexp, handler func(http.ResponseWriter, *http.Request)) {
h.routes = append(h.routes, &route{pattern, http.HandlerFunc(handler)})
}
func (h *RegexpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
for _, route := range h.routes {
if route.pattern.MatchString(r.URL.Path) {
route.handler.ServeHTTP(w, r)
return
}
}
// no pattern matched; send 404 response
http.NotFound(w, r)
}
Run Code Online (Sandbox Code Playgroud)
Von*_*onC 55
自2011年起,您现在可以(2014年以上)找到其他解决方案.
例如,Gorilla Web工具包的mux包提供了所有类型的路由选项:
它可以很容易地集成到任何BYOR(带自己的路由器)http库,如negroni.
以下是文章" Gorilla vs Pat vs Routes:Mux Showdown "中的一个例子:
package main
import (
"github.com/gorilla/mux"
"log"
"net/http"
)
func main() {
rtr := mux.NewRouter()
rtr.HandleFunc("/user/{name:[a-z]+}/profile", profile).Methods("GET")
http.Handle("/", rtr)
log.Println("Listening...")
http.ListenAndServe(":3000", nil)
}
func profile(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
name := params["name"]
w.Write([]byte("Hello " + name))
}
Run Code Online (Sandbox Code Playgroud)
有时最好不要只使用另一个"神奇"的包装,但要了解引擎盖下发生了什么
在这种情况下,"魔术"在" gorilla/mux/regexp.go
"中定义,并在此处进行测试.
我们的想法是提取命名变量,组装要匹配的正则表达式,创建"反向"模板以构建URL并编译正则表达式以验证URL构建中使用的变量值.
我只是想添加julienschmidt/httprouter
,它只是行为,net/http
但有一个额外的url值参数和对请求方法的支持:
https://github.com/julienschmidt/httprouter
package main
import (
"fmt"
"github.com/julienschmidt/httprouter"
"net/http"
"log"
)
func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
fmt.Fprint(w, "Welcome!\n")
}
func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name"))
}
func main() {
router := httprouter.New()
router.GET("/", Index)
router.GET("/hello/:name", Hello)
log.Fatal(http.ListenAndServe(":8080", router))
}
Run Code Online (Sandbox Code Playgroud)
它似乎比gorilla/mux
(根据GitHub)稍微更受欢迎,并且它还声称需要更少的内存.
https://github.com/julienschmidt/go-http-routing-benchmark
这是如何使用来自@evanshaw 的代码示例的示例
func handleDigits(res http.ResponseWriter, req *http.Request) {
res.Write([]byte("Digits in the URL\n"))
}
func handleStrings(res http.ResponseWriter, req *http.Request) {
res.Write([]byte("Strings in the URL\n"))
}
func main() {
handler := &RegexpHandler{}
reg1, _ := regexp.Compile("/foo-\\d+")
handler.HandleFunc(reg1, handleDigits)
reg2, _ := regexp.Compile("/foo-\\w+")
handler.HandleFunc(reg2, handleStrings)
http.ListenAndServe(":3000", handler)
}
Run Code Online (Sandbox Code Playgroud)