Go1-22 新特性:增強 http-ServerMux 路由能力,將有更強的表現力!
大家好,我是煎魚。
Go1.22 有一個比較重要的新特性,那就是基於提案《net/http: enhanced ServeMux routing[1]》,增強了 http.ServerMux 的路由匹配能力。非常值得大家學習和關注。
本次的新特性主要是新增了 HTTP 方法和路徑變量的支持。
快速學習
在 Go 中,可以認爲幾乎所有的路由相關的庫都會基於 net/http 或是兼容其 interface。否則容易脫離一個標準路線。
本文的主角 ServeMux,函數簽名如下:
type ServeMux
func NewServeMux() *ServeMux
func (mux *ServeMux) Handle(pattern string, handler Handler)
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request))
func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string)
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request)
最簡單的 Demo 如下:
type apiHandler struct{}
func (apiHandler) ServeHTTP(http.ResponseWriter, *http.Request) {}
func main() {
mux := http.NewServeMux()
mux.Handle("/api/", apiHandler{})
mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
...
fmt.Fprintf(w, "你好,煎魚!)
})
}
用法非常的簡單和標準,就是路徑和實現方法。
新提案
緣由
這個提案居然沒有顯著的說明沒有這個的缺陷或問題。說明大家在潛意識裏已經是比較認可的,不需要額外解釋。
我大膽猜測原因應該是:net/http.ServeMux所提供的路由功能過於的基礎了。
因此路由使用上,很多人都不優先推薦使用 net/http,而是更推薦 gorilla/mux 等知名開源庫作爲基礎庫,提高實現的效率和產能。
本次新提案將會增加:模式匹配、路徑變量的支持。
Go1.22 路由增強
匹配方法
模式匹配將支持以 HTTP 方法開頭,後跟空格,如 GET /eddycjy 或 GET eddycjy.com/ 中。帶有方法的模式僅用於匹配具有該方法的請求。
對照到代碼中,也就是 Go1.22 起,http.ServeMux 可以這麼寫:
mux.HandleFunc("POST /eddycjy/create", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "腦子進煎魚了!")
})
mux.HandleFunc("GET /eddycjy/update", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "煎魚進腦子了...")
})
...
通配符
模式匹配將支持 {name} 或 {name...},例如:/b/{bucket}/o/{objectname...}。
該名稱必須是有效的 Go 標識符和符合完整路徑元素的標準。它們前面必須有斜槓,後面必須有斜槓或字符串末尾。例如:/b_{bucket} 不是有效的通配模式。
Go1.22 起,http.ServeMux 可以這麼寫:
mux.HandleFunc("/eddycjy/{id}", func(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
fmt.Fprintf(w, "id 值爲 %s", id)
})
mux.HandleFunc("/eddycjy/{path...}", func(w http.ResponseWriter, r *http.Request) {
path := r.PathValue("path")
fmt.Fprintf(w, "path 值爲 %s", path)
})
...
優先級
單一的優先規則:
-
如果兩個模式重疊(有一些共同的請求),那麼更具體的模式優先。
-
如果 P1 符合 P2 請求的一個(嚴格)子集,也就是說:如果 P2 符合 P1 的所有請求及更多請求,那麼 P1 就比 P2 更具體。
-
如果兩者都不更具體,那麼模式就會發生衝突。
-
這條規則有一個例外:如果兩個模式發生衝突,而其中一個有 HOST ,另一個沒有,那麼有 HOST 的模式優先。
以下是圖示參考:
具體的例子:
-
example.com/比/更具體,因爲第一個僅匹配主機example.com的請求,而第二個匹配任何請求。 -
GET /比/更具體,因爲第一個僅匹配 GET 和 HEAD 請求,而第二個匹配任何請求。 -
/b/{bucket}/o/default比/b/{bucket}/o/{noun}更具體,因爲第一個僅匹配第四個元素是文字 “default” 的路徑,而在第二個中,第四個元素可以是任何內容。
總結
今天我們分享了 Go1.22 對於 net/http 標註庫中的 ServerMux 路由相關功能的增強。
Go 還是有在吸收第三方開源庫的一些不錯的地方的,就是慢了一些。這都 10 多年了...
參考資料
[1]
net/http: enhanced ServeMux routing: https://github.com/golang/go/issues/61410
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/5-wgwSJWAsWqwaAh3kS69g