【Golang源码分析】Go Web常用程序包gorilla/mux的使用与源码简析
目錄【閱讀時間:約10分鐘】
- 一.概述
- 二.對比: gorilla/mux與net/http DefaultServeMux
- 三.簡單使用
- 四.源碼簡析
- 1.NewRouter函數
- 2.HandleFunc函數
- 設置路由的HTTP方法
- 設置路由的域名
- 限制HTTP 方案
- 設置路徑前綴和子路由
- 3.PathPrefix函數
- 五.References
一.概述
gorilla/mux程序包,是一個強大的url路由和調度器,它具有小巧但是穩定高效的特性。
不僅可以支持正則路由,還可以按照Method、header、host等信息匹配,可以從我們設定的路由表達式中提取出參數方便上層應用,而且完全兼容http.ServerMux。
二.對比: gorilla/mux與net/http DefaultServeMux
Go 官方標準庫 net/http 自帶的 DefaultServeMux 底層實現,通過 DefaultServeMux 提供的路由處理器雖然簡單易上手,但是存在很多不足,比如:
- 不支持參數設定,例如
/user/:uid這種泛類型匹配; - 對 REST 風格接口支持不友好,無法限制訪問路由的方法;
- 對于擁有很多路由規則的應用,編寫大量路由規則非常繁瑣。
為此,我們可以使用第三方庫 gorilla/mux 提供的更加強大的路由處理器(mux 代表 HTTP request multiplexer,即 HTTP 請求多路復用器),和 http.ServeMux 實現原理一樣,gorilla/mux 提供的路由器實現類 mux.Router 也會匹配用戶請求與系統注冊的路由規則,然后將用戶請求轉發過去。
mux.Router 主要具備以下特性:
- 實現了
http.Handler接口,所以和http.ServeMux完全兼容; - 可以基于 URL 主機、路徑、前綴、scheme、請求頭、請求參數、請求方法進行路由匹配;
- URL 主機、路徑、查詢字符串支持可選的正則匹配;
- 支持構建或反轉已注冊的 URL 主機,以便維護對資源的引用;
- 支持路由嵌套(類似 Laravel 中的路由分組),以便不同路由可以共享通用條件,比如主機、路徑前綴等。
三.簡單使用
安裝程序包:
go get -u github.com/gorilla/mux
樣例①:
基于Golang的簡單web服務程序開發——CloudGo
主要的相關函數為NewServer函數與initRoutes函數:
// NewServer configures and returns a Server.
func NewServer() *negroni.Negroni {formatter := render.New(render.Options{Directory: "templates",Extensions: []string{".html"},IndentJSON: true,})n := negroni.Classic()mx := mux.NewRouter()initRoutes(mx, formatter)n.UseHandler(mx)return n
}func initRoutes(mx *mux.Router, formatter *render.Render) {webRoot := os.Getenv("WEBROOT")if len(webRoot) == 0 {if root, err := os.Getwd(); err != nil {panic("Could not retrive working directory")} else {webRoot = root//fmt.Println(root)}}mx.HandleFunc("/api/test", apiTestHandler(formatter)).Methods("GET")mx.HandleFunc("/", homeHandler(formatter)).Methods("GET")mx.HandleFunc("/user", userHandler).Methods("POST")mx.PathPrefix("/").Handler(http.FileServer(http.Dir(webRoot + "/assets/")))
}
樣例②:
package mainimport ("fmt""github.com/gorilla/mux""log""net/http"
)func sayHelloWorld(w http.ResponseWriter, r *http.Request) {w.WriteHeader(http.StatusOK) // 設置響應狀態碼為 200fmt.Fprintf(w, "Hello, World!") // 發送響應到客戶端
}func main() {r := mux.NewRouter()r.HandleFunc("/hello", sayHelloWorld)log.Fatal(http.ListenAndServe(":8080", r))
}
在 main 函數中的第一行顯式初始化了 mux.Router 作為路由器,然后在這個路由器中注冊路由規則,最后將這個路由器傳入 http.ListenAndServe 方法,整個調用過程和之前并無二致,因為我們前面說了,mux.Router 也實現了 Handler 接口。
運行這段代碼,在瀏覽器訪問 http://localhost:8080/hello,即可渲染出如下結果:
Hello, World!
四.源碼簡析
gorilla/mux源碼可分為context、mux、regex、route四個部分,在CloudGo項目開發過程中,我主要使用了NewRouter、HandleFunc和PathPrefix這三個函數。下面對這三個函數進行分析:
1.NewRouter函數
Router是一個結構體,如下:
type Router struct {// Configurable Handler to be used when no route matches.NotFoundHandler http.Handler// Configurable Handler to be used when the request method does not match the route.MethodNotAllowedHandler http.Handler// Parent route, if this is a subrouter.parent parentRoute// Routes to be matched, in order.routes []*Route// Routes by name for URL building.namedRoutes map[string]*Route// See Router.StrictSlash(). This defines the flag for new routes.strictSlash bool// See Router.SkipClean(). This defines the flag for new routes.skipClean bool// If true, do not clear the request context after handling the request.// This has no effect when go1.7+ is used, since the context is stored// on the request itself.KeepContext bool// see Router.UseEncodedPath(). This defines a flag for all routes.useEncodedPath bool
}
調用NewRouter函數可用來實例化一個Router:
// NewRouter returns a new router instance.
func NewRouter() *Router {return &Router{namedRoutes: make(map[string]*Route), KeepContext: false}
}
這里可以看見,它開辟了一個裝Route指針的map,然后默認該Router的KeepContext為false,意思是在請求被處理完之后清除該請求的上下文。
2.HandleFunc函數
// HandleFunc registers a new route with a matcher for the URL path.
// See Route.Path() and Route.HandlerFunc().
func (r *Router) HandleFunc(path string, f func(http.ResponseWriter,*http.Request)) *Route {return r.NewRoute().Path(path).HandlerFunc(f)
}
若只觀察HandleFunc函數,會發現其代碼只有幾行,其主要功能是使用URL的匹配器注冊新路由。
gorilla/mux的HandleFunc函數功能很強大,主要有以下功能:
設置路由的HTTP方法
限制路由處理器只處理指定的HTTP方法的請求:
router.HandleFunc("/books/{title}", CreateBook).Methods("POST")
router.HandleFunc("/books/{title}", ReadBook).Methods("GET")
router.HandleFunc("/books/{title}", UpdateBook).Methods("PUT")
router.HandleFunc("/books/{title}", DeleteBook).Methods("DELETE")
上面的就是一組可以響應具體HTTP方法的RESTful風格的接口的路由。
設置路由的域名
限制路由處理器只處理訪問指定域名加路由的請求:
router.HandleFunc("/books/{title}", BookHandler).Host("www.mybookstore.com")
限制HTTP 方案
將請求處理程序可響應的HTTP方案限制為http或者https。
router.HandleFunc("/secure", SecureHandler).Schemes("https")
router.HandleFunc("/insecure", InsecureHandler).Schemes("http")
設置路徑前綴和子路由
bookrouter := router.PathPrefix("/books").Subrouter()
bookrouter.HandleFunc("/", AllBooks)
bookrouter.HandleFunc("/{title}", GetBook)
3.PathPrefix函數
// PathPrefix registers a new route with a matcher for the URL path prefix.
// See Route.PathPrefix().
func (r *Router) PathPrefix(tpl string) *Route {return r.NewRoute().PathPrefix(tpl)
}
PathPrefix函數源碼也只有幾行,它的功能只是簡單地增加URL的前綴,通常結合HandleFunc函數和Handler函數來使用。
五.References
- 基于 gorilla/mux 包實現路由定義和請求分發:基本使用
- gorilla/mux類庫解析
- Gorilla源碼分析之gorilla/mux源碼分析
- 從一個例子分析gorilla/mux源碼
- gorilla/mux官方GitHub
總結
以上是生活随笔為你收集整理的【Golang源码分析】Go Web常用程序包gorilla/mux的使用与源码简析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于Golang的简单web服务程序开发
- 下一篇: 【CentOS】利用Kubeadm部署K