Go Web 路由處理利器 gorilla/mux 庫

Aklman發表於2021-05-24

1. gorilla/mux 是什麼?

gorilla/mux 是用來處理路由請求和請求對應的方法的對映關係的包,簡單地說,gorilla/mux 就是把收到的請求與一組預先定義的 URL 路徑列表做對比,然後在匹配到路徑的時候呼叫關聯的處理器(Handler)。

2. 為什麼那麼受歡迎?

gorilla/mux 在標準庫 net/http 之上開發的,因此 gorilla/mux 比較能幹,標準能幹的也能幹,不能幹的也能幹;標準庫在執行效率上佔優,gorilla/mux 在開發效率上佔優;,gorilla/mux 是目前功能最為強大的路由包之一,它提供功能全面而強大,這也是它連續多年成為使用率最高的 Go 第三方包的原因。

3. 什麼時候用到它?

gorilla/mux 的路由解析所採用的是精準匹配規則,標準庫 net/http 採用的是長度優先匹配規則,精準匹配是隻會匹配準確指定的路由,而長度優先匹配不支援動態元素,也就是不支援正則以及 URL 路徑引數,只能匹配字元數較多的路由;開發 Web,API 時路由一般時動態的,路由引數會跟著訪問物件不同而不同,這是 gorilla/mux 恰好滿足了這種精準路由匹配需求。

在知名的路由包中 gorilla/mux 的功能比較強大,使用相對簡單且很實,歷史也非常悠久,可以放心去使用。

4. 怎麼使用它?

使用前要安裝它,安裝要在當前專案所在目錄中執行 go get -u github.com/gorilla/mux 即可。

安裝完寫一個 Web 應用示例:

package main

import (
    "fmt"
    "net/http"

    "github.com/gorilla/mux"
)

func homeHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "<h1>This is homePage!</h1>")
}

func articlesIndexHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "<h1>This is articlesIndexPage!</h1>")
}

func notFoundHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "<h1>This is notFoundPage</h1>")
}

func articlesShowHandler(w http.ResponseWriter, r *http.Request) {
    //mux 提供 mux.Vars(r) 的方法會將 URL 路徑引數解析為 Map, key 是路由引數,value 是引數對應的值,
    vars := mux.Vars(r)
    id := vars["id"]
    fmt.Fprint(w, "<h1>This articles‘s ID:"+id+"</h1>")
}

func articlesStoreHandler(w http.ResponseWriter, r *http.Request) {
    //獲取表單中傳輸的資料方式有 r.ParseForm, ParseFormValue 等,具體如下:
    //r.ParseForm() 是由標準庫 http 包提供的,從請求中解析請求引數,必須是執行完這段程式碼,
    //再用 r.PostForm 和 r.Form 來獲取到資料,不事先 r.ParseForm() 來解析時獲取不到資料。
    err := r.ParseForm()
    if err != nil {
        fmt.Fprint(w, "請在表單中填寫資料再提交!")
        return
    }

    title := r.PostForm.Get("title")
    content := r.PostForm.Get("content")
    author := r.PostForm.Get("author")
    fmt.Fprintf(w, "title 的值為: %v", title)
    fmt.Fprintf(w, "content 的值為: %v", content)
    fmt.Fprintf(w, "author 的值為: %v", author)

    //PostForm 只能能讀取 post、put 方式傳輸的引數,在使用之前需要呼叫 ParseForm 方法。
    fmt.Fprintf(w, "POST PostForm: %v <br>", r.PostForm)
    //Form 能讀取 post、put 和 get 方式傳輸的引數,在使用之前必須呼叫 ParseForm 方法來解析路由
    fmt.Fprintf(w, "POST Form: %v <br>", r.Form)
    //  直接獲取想要的引數,則直接使用 r.PostFormValue() 方法即可,無需呼叫 ParseForm 方法來解析路由
    fmt.Fprintf(w, "r.Form() 中 title 的值為: %v <br>", r.FormValue("title"))
    fmt.Fprintf(w, "r.PostForm() 中 title 的值為: %v <br>", r.PostFormValue("title"))
}


func main() {
    //註冊路由
    router := mux.NewRouter()

    //精準匹配的
    router.HandleFunc("/", homeHandler).Methods("GET").Name("home")
    router.HandleFunc("/articles/{id:[0-9]+}", articlesShowHandler).Methods("GET").Name("articles.show")
    router.HandleFunc("/articles", articlesIndexHandler).Methods("GET").Name("articles.index")
    router.HandleFunc("/articles/{id:[0-9]+}", articlesStoreHandler).Methods("GET").Name("articles.store")

    //未匹配到路由時匹配到 notFoundHandler
    router.NotFoundHandler = http.HandlerFunc(notFoundHandler)

    //監聽路由
    http.ListenAndServe(":6060", router)
}

寫完示例,執行 go run main.go 啟動 Web 服務;再用 Postman 來訪問一下 url 即可看到返回結果。

  • GET 方式訪問 localhost:6060/
  • GET 方式訪問 localhost:6060/articls
  • GET 方式訪問 localhost:6060/articles/2
  • POST 方式訪問 localhost:6060/articles

以上的所以路由中用到了路由別名 router.HandleFunc(_, _).Methods("GET")..Name("別名")' ,除此之外在articlesIndexHandler).Methods("GET").Name("articles.index") router.HandleFunc("/articles/{id:[0-9]+}", ` 中用到了動態路由,也就是 id 不一樣展示的物件也不一樣。

除了提供 Web 開發常用功能之外,gorilla/mux 包還提供其他一些功能,比如,域名繫結,路由分組,路由繫結字首,路由中介軟體等,看具體業務需求選擇性使用即可。

5. 總結

gorilla/mux 庫是歷史悠久,從使用文件齊全、其質量和社群活躍度都很 nice,多年 Go 趨勢報告中指出 gorilla/mux 是整個社群使用率最高的第三方庫,佔據 36% 的市場份額。

gorilla/mux 使用方式簡單,擴充套件性好,功能強大且全面,也可以根據自身業務需要對它進行定製化的二次開發。

gorilla/mux 能大大提升 Web 應用開發效率,使用簡單不粗暴。

6. 參考資料

更多原創文章乾貨分享,請關注公眾號
  • Go Web 路由處理利器 gorilla/mux 庫
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章