1. 程式人生 > >go web: 3 中介軟體和路由

go web: 3 中介軟體和路由

中介軟體

中介軟體的本質來看,就是在執行handler的前(後)先執行一個自定義的handler而已。那問題變成,go web中,每個handler是怎麼執行的。

答案在mux := http.NewServeMux()中,稍微閱讀下原始碼,我們就能得出,mux物件中有個ServeHTTP(w, r)方法。這就祕密所在。

根據go的鴨子型別特性,我們完全可以實現一個結構,然後讓它擁有ServeHTTP(w, r)方法。把這個結構替換掉http.Server物件中的Handler,就能自定義hander的執行。既然都能控制handler運行了,中介軟體什麼的還不是小case。

然而還能更簡單,可愛的go語言還在http包中,提供了一個http.HandlerFunc(ourFunc)

方法,它能把簽名為func(w http.ResponseWriter, r *http.Request)的函式轉化為一個handler,沒錯,就是上面mux相同的型別。
要實現自己的mux,可以只是一個簡單的函式:

// myHost 做中介軟體
func myHost(handler http.Handler) http.Handler {
    ourFunc := func(w http.ResponseWriter, r *http.Request) {
        //記錄時間
        start := time.Now()
        handler.ServeHTTP
(w, r) logger.Infoln( fmt.Sprintf("%s %s %s", r.Method, r.URL, time.Now().Sub(start))) } return http.HandlerFunc(ourFunc) }

這個“記錄時間”的操作,不就是最簡單的中介軟體嗎?
main.go中的呼叫則改成:

mux := http.NewServeMux()
mh := myHost(mux)
server :=
    http.Server{
        Addr:         fmt.Sprintf
(":%d", options.GetInt("port")), Handler: mh, ReadTimeout: 3 * time.Second, WriteTimeout: 5 * time.Second, } // 開始新增路由 mux.HandleFunc("/hi", test.SayHello) server.ListenAndServe()

路由

既然我們能通過hack ServeHTTP來控制handler的呼叫,那實現路由還不是順水推舟。
在server.go中看看mux.ServeHTTPmux.handler這兩個函式原始碼,這個簡單而蛋疼的預設路由就躍然紙上。
對於路由,我們沒必要自己寫ServeHttp和match規則,因為太麻煩了。
所以,我們google下 httprouter這個包。輪子都造好了。