1、什麼是httprouter
httprouter
談不上是一個框架,它的效能非常優秀。完全可以用來代替預設的 ServeMux
。
所以比較適合對效能要求高,路由相對簡單扁平的業務,或者作為高層HTTP框架的內部模組。
httproute內部通過實現一個trie樹來提高效能。
核心程式碼就是golang標準庫中 http.Handler 介面,在該函式中實現自己的請求路由分發策略。
gorilla/mux也是一個第三方的路由器,但是效能一般
2、為什麼用httprouter
說說net/http的不足:
- 不能單獨的對請求方法(POST,GET等)註冊特定的處理函式
- 不支援路由變數引數
- 不能自動對Path進行校準
- 效能一般、擴充套件性不足
httprouter帶來哪些便利?
- 僅支援
精確匹配
,及只匹配一個模式或不會匹配到任何模式。相對於其他一些mux,例如go原生的 http.ServerMux, 會使得一個請求URL匹配多個模式,從而需要有優先順序順序,例如最長匹配、最先匹配等等。 - 不需要關心URL
結尾的斜槓
- 路徑自動歸一化和矯正
- 零記憶體分配、高效能
3、httprouter路由匹配
net/http的路由匹配
// /api,可以訪問到
// /api/,不可以
http.HandleFunc("/api",func(w http.ResponseWriter,r *http.Request){
fmt.Println("/api")
})
// /api,可以
// /api/,也可以
http.HandleFunc("/api/",func(w http.ResponseWriter,r *http.Request){
fmt.Println("/api")
})
複製程式碼
httprouter的路徑匹配規則
兩個路由命名捕獲方式:(==路由命名的捕獲,不是路由引數的捕獲==)
:name
named parameter (只能根據路由命名進行捕獲)*name
catch-all parameter (*表示捕獲任意內容)
其中:name
的捕獲方式是匹配內容直到下一個斜線或者路徑的結尾。例如要為如下路徑註冊 handler:
Path: /blog/:category/:post
router.GET("/blog/:category/:post", Hello) //(category/post可以看成是一個變數)
當請求路徑為:
/blog/go/request-routers match: category="go", post="request-routers"
/blog/go/request-routers/ no match, but the router would redirect
/blog/go/ no match
/blog/go/request-routers/comments no match
複製程式碼
*name
的捕獲方式是從指定位置開始 (包含字首 "/") 匹配到結尾:
Path: /files/*filepath */
router.GET("/files/*filepath", Hello) //filepath可以看成是一個變數
當請求路徑為:
/files/ match: filepath="/"
/files/LICENSE match: filepath="/LICENSE"
/files/templates/article.html match: filepath="/templates/article.html"
/files no match, but the router would redirect
複製程式碼
4、httprouter重定向
func New() *Router {
return &Router{
//是否啟用自動重定向。
//比如請求/foo/,但是隻有/foo的handler,則httprouter內部使用301重定向到/foo進行GET處理。
//檢視瀏覽器可以看到301的請求,可以看到請求頭的location:/foo
//直接get,然後響應一個字串,這裡的文字型別是text/plain,其實就是txt檔案
//這也就為什麼,只有/foo的handler時,請求/foo/會404,因為/foo/代表著foo目錄,預設會請求/foo/index.html,不就404了
RedirectTrailingSlash: true,
RedirectFixedPath: true,
HandleMethodNotAllowed: true,
//如果啟用,則路由器會自動回覆OPTIONS請求
HandleOPTIONS: true,
}
}
複製程式碼
5、lookup
func (r *Router) Lookup(method, path string) (Handle, Params, bool)
複製程式碼
Lookup根據method+path檢索對應的Handle,以及Params,並可以通過第三個返回值判斷是否會進行重定向。
6、關於引數
除了路由引數,還有URL的query
引數,也就是?a=b&c=d
這樣的格式
query引數
//url引數解析
http.HandleFunc("/api/", func(w http.ResponseWriter, r *http.Request) {
values := r.URL.Query()
fmt.Println(values)
})
//result
//http://127.0.0.1:9090/api/?a=1&b=2&c=3
//map[a:[1] b:[2] c:[3]]
複製程式碼
路由引數
//使用場景有哪些呢??
/users/123
/users/456
/users/23456
比如有很多使用者,如上,我們需要為一個個使用者去註冊路由?顯然不現實
這時就可以使用路由引數了,/users/id
複製程式碼