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)
})
...

優先級

單一的優先規則:

  1. 如果兩個模式重疊(有一些共同的請求),那麼更具體的模式優先。

  2. 如果 P1 符合 P2 請求的一個(嚴格)子集,也就是說:如果 P2 符合 P1 的所有請求及更多請求,那麼 P1 就比 P2 更具體。

  3. 如果兩者都不更具體,那麼模式就會發生衝突。

  4. 這條規則有一個例外:如果兩個模式發生衝突,而其中一個有 HOST ,另一個沒有,那麼有 HOST 的模式優先。

以下是圖示參考:

具體的例子:

總結

今天我們分享了 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