Golang 第三方庫學習 · mux

本文為轉載,原文:Golang 第三方庫學習 · mux

Golang

介紹

mux 是一個用來執行http請求的路由和分發的第三方擴展包。

mux 其名稱來源于HTTP request multiplexer,類似于官方包http.ServeMuxmux.Router將會定義一個路由列表,其中每一個路由都會定義對應的請求url,及其處理方法。

源碼

第三方庫源碼:
https://github.com/gorilla/mux
本文源碼:
https://github.com/Chain-Zhang/third-lib

安裝

go get -u github.com/gorilla/mux

使用

添加包引用:

"github.com/gorilla/mux"

常用方法介紹

初始化路由

r := mux.NewRouter()

路由注冊

最簡單的路由注冊:

r.HandleFunc("/", HomeHandler)

其中代碼中的第一個參數為請求url,第二個參數為請求的處理函數,該函數可簡單的定義為以下代碼:

func HomeHandler(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusOK)
    fmt.Fprintf(w, "this is home")
}

帶有變量的url路由注冊:
其中參數可使用正則表達式匹配

r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler)

指定Host:

r.Host("www.example.com")

指定http方法:

r.Methods("GET", "POST")

指定URL安全策略:

r.Schemes("https")

增加URL前綴:

r.PathPrefix("/products/")

添加請求頭:

r.Headers("X-Requested-With", "XMLHttpRequest")

添加請求參數:

r.Queries("key", "value")

組合使用:

r.HandleFunc("/products", ProductsHandler).
  Host("www.example.com").
  Methods("GET").
  Schemes("http")

子路由的使用:

r := mux.NewRouter()
s := r.PathPrefix("/products").Subrouter()
// "/products/"
s.HandleFunc("/", ProductsHandler)
// "/products/{key}/"
s.HandleFunc("/{key}/", ProductHandler)
// "/products/{key}/details"
s.HandleFunc("/{key}/details", ProductDetailsHandler)

定義路由別名:

r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).Name("article")

靜態文件路由:

flag.StringVar(&dir, "dir", ".", "the directory to serve files from. Defaults to the current dir")
flag.Parse()
r := mux.NewRouter()

 // This will serve files under http://localhost:8000/static/<filename>
    r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(dir))))

生成已注冊的URL:
生成已注冊的url需要用到路由的別名,代碼如下:

url, err := r.Get("router_name").URL("key1", "val1", "key2", "val2")

例如:

r := mux.NewRouter()
r.Host("{subdomain}.domain.com").
  Path("/articles/{category}/{id:[0-9]+}").
  Queries("filter", "{filter}").
  HandlerFunc(ArticleHandler).
  Name("article")

// url.String() will be "http://news.domain.com/articles/technology/42?filter=gorilla"
url, err := r.Get("article").URL("subdomain", "news",
                                 "category", "technology",
                                 "id", "42",
                                 "filter", "gorilla")

Walk方法:
walk方法可以遍歷訪問所有已注冊的路由,例如以下代碼:

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/", handler)
    r.HandleFunc("/products", handler).Methods("POST")
    r.HandleFunc("/articles", handler).Methods("GET")
    r.HandleFunc("/articles/{id}", handler).Methods("GET", "PUT")
    r.HandleFunc("/authors", handler).Queries("surname", "{surname}")
    err := r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
        pathTemplate, err := route.GetPathTemplate()
        if err == nil {
            fmt.Println("ROUTE:", pathTemplate)
        }
        pathRegexp, err := route.GetPathRegexp()
        if err == nil {
            fmt.Println("Path regexp:", pathRegexp)
        }
        queriesTemplates, err := route.GetQueriesTemplates()
        if err == nil {
            fmt.Println("Queries templates:", strings.Join(queriesTemplates, ","))
        }
        queriesRegexps, err := route.GetQueriesRegexp()
        if err == nil {
            fmt.Println("Queries regexps:", strings.Join(queriesRegexps, ","))
        }
        methods, err := route.GetMethods()
        if err == nil {
            fmt.Println("Methods:", strings.Join(methods, ","))
        }
        fmt.Println()
        return nil
    })

    if err != nil {
        fmt.Println(err)
    }

    http.Handle("/", r)
}

Middleware 中間件

mux同樣也支持為路由添加中間件。

最簡單的中間件定義:

func loggingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // Do stuff here
        log.Println(r.RequestURI)
        // Call the next handler, which can be another middleware in the chain, or the final handler.
        next.ServeHTTP(w, r)
    })
}

中間件使用:

r := mux.NewRouter()
r.HandleFunc("/", handler)
r.Use(loggingMiddleware)

綜合示例

package th_mux

import(
    "strings"
    "flag"
    "fmt"
    "net/http"
    "github.com/gorilla/mux"
)

func Run(){
    var dir string
    flag.StringVar(&dir, "dir", ".", "the directory to serve files from. Defaults to the current dir")
    flag.Parse()
    // 初始化Router
    r := mux.NewRouter()
    // 靜態文件路由
    r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(dir))))
    // 普通路由
    r.HandleFunc("/", HomeHandler)
    // 指定host
    r.HandleFunc("/host", HostHandler).Host("localhost")
    // 帶變量的url路由
    r.HandleFunc("/users/{id}", GetUserHandler).Methods("Get").Name("user")

    url, _ := r.Get("user").URL("id", "5")
    fmt.Println("user url: ", url.String())

    // 遍歷已注冊的路由
    r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
        pathTemplate, err := route.GetPathTemplate()
        if err == nil {
            fmt.Println("ROUTE:", pathTemplate)
        }
        pathRegexp, err := route.GetPathRegexp()
        if err == nil {
            fmt.Println("Path regexp:", pathRegexp)
        }
        queriesTemplates, err := route.GetQueriesTemplates()
        if err == nil {
            fmt.Println("Queries templates:", strings.Join(queriesTemplates, ","))
        }
        queriesRegexps, err := route.GetQueriesRegexp()
        if err == nil {
            fmt.Println("Queries regexps:", strings.Join(queriesRegexps, ","))
        }
        methods, err := route.GetMethods()
        if err == nil {
            fmt.Println("Methods:", strings.Join(methods, ","))
        }
        fmt.Println()
        return nil
    })

    r.Use(TestMiddleware)
    http.ListenAndServe(":3000", r)
}

func HomeHandler(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusOK)
    fmt.Fprintf(w, "this is home")
}

func HostHandler(w http.ResponseWriter, r *http.Request){
    w.WriteHeader(http.StatusOK)
    fmt.Fprintf(w, "the host is localhost")
}

func GetUserHandler(w http.ResponseWriter, r *http.Request){
    vars := mux.Vars(r)
    w.WriteHeader(http.StatusOK)
    
    fmt.Fprint(w, "this is get user, and the user id is ", vars["id"])
}


func TestMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // Do stuff here
        fmt.Println("middleware print: ", r.RequestURI)
        // Call the next handler, which can be another middleware in the chain, or the final handler.
        next.ServeHTTP(w, r)
    })
}

運行結果截圖
剛執行時的注冊打印:

注冊

依次在瀏覽器中輸入以下地址測試,查看結果:

http://localhost:3000/
http://localhost:3000/host
http://127.0.0.1:3000/host
http://localhost:3000/users/5

轉載請注明出處:Golang 第三方庫學習 · mux

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容