今天這篇文章咱們將會爲咱們以前編寫的HTTP
服務器加上覆雜路由的功能以及對路由進行分組管理。在以前的文章《深刻學習用 Go 編寫HTTP服務器》中詳細地講了使用net/http
進行路由註冊、監聽網絡鏈接、處理請求、安全關停服務的實現方法,使用起來很是方便。可是net/http
有一點作的不是很是好的是,它沒有提供相似URL
片斷解析、路由參數綁定這樣的複雜路由功能。好在在Go
社區中有一個很是流行的gorilla/mux
包,它提供了對複雜路由功能的支持。在今天這篇文章中咱們將探究如何用gorilla/mux
包來建立具備命名參數、GET/POST
處理、分組前綴、限制訪問域名的路由。git
gorilla/mux
包咱們在以前寫的HTTP
服務的代碼根目錄,使用go get命令從GitHub安裝軟件包,以下所示:github
go get github.com/gorilla/mux
在《深刻學習用 Go 編寫HTTP服務器》中咱們介紹過路由註冊、匹配和最後處理函數的調用都是由ServeMux
(服務複用器)來完成的,並且咱們還本身定義了複用器用以替換默認的DefaultServeMux
。一樣的gorilla/mux
包也是爲咱們提供了一個複用器。這個複用器擁有不少功能用以提高編寫Web
應用的效率,並且與標準的http.ServeMux
兼容。正則表達式
gorilla/mux
包能夠像下面這樣建立一個路由器安全
router := mux.NewRouter()
會返回一個mux.Router
實例,mux.Router
將傳入的請求與已註冊路由列表進行匹配,併爲與URL
或其餘條件匹配的路由調用處理程序。主要特色是:服務器
Header
頭、查詢值,HTTP
方法進行路由匹配,或是使用自定義匹配器。http.ServeMux
徹底兼容。咱們將以前程序裏自定義的服務複用器替換成上面建立好mux.Router
,併爲其註冊路由處理器。網絡
type helloHandler struct{} func (*helloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello World") } func WelcomeHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Welcome!") } func main() { router := mux.NewRouter() router.Handle("/", &helloHandler{}) router.HandleFunc("/welcome", WelcomeHandler) ...... }
以前咱們是用http.Hanle
,http.HandleFunc
註冊處理程序的,這裏直接換成router.Hanle
和router.HanleFunc
便可,很方便。函數
使用mux.Router
的最大優點是能夠從請求URL
中提取分段,而後做爲命名參數傳入路由處理程序供使用。學習
接下來爲咱們的程序註冊一個路由處理器,讓服務器可以處理URL
爲/names/Gorge/countries/NewZealand
的請求:spa
router.HandleFunc("/names/{name}/countries/{country}", func(writer http.ResponseWriter, request *http.Request) { ...... })
接下來在處理函數中使用mux.Vars()
函數從這些URL
分段中獲取數據。該函數以http.Request
爲參數並返回一個URL
分段名爲鍵,提取的數據爲值的字典。code
func(writer http.ResponseWriter, request *http.Request) { vars := mux.Vars(request) name := vars["name"] country := vars["country"] fmt.Fprintf(writer, "This guy named %s, was coming from %s .", name, country) })
這個設置很簡單,若是沒有自定義http.Server
對象,使用http.ListenAndServe(":8000", router)
,使用本身定義的`http.Server 對象時則是:
server := &http.Server{ Addr: ":8080", Handler: router, }
這個和咱們把自定義的服務複用器傳遞給http.Server
沒有任何區別。
改造完後咱們以前寫的HTTP
服務器就能夠根據具體的 URL 動態地構造響應。關鍵字回覆http02
可得到完整的源代碼
gorilla/mux
路由器的經常使用功能限制路由處理器只處理指定的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
或者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)
gorilla/mux
改進咱們的HTTP
服務器接下來咱們使用gorilla/mux
對咱們以前寫的HTTP
服務器作一下改進,以前咱們全部程序都放在了main.go
中,如今咱們的程序還很小,因此咱們先不把項目目錄規劃的太複雜,先經過文件作下簡單的職責劃分,新建兩個文件router.go
和handler.go
分別用來存放路由註冊的邏輯和路由對應的處理器函數,兩個文件的示例內容以下。
handler.go
:
package main import ( "fmt" "github.com/gorilla/mux" "net/http" ) type HelloHandler struct{} func (*HelloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello World") } func ShowVisitorInfo(writer http.ResponseWriter, request *http.Request) { vars := mux.Vars(request) name := vars["name"] country := vars["country"] fmt.Fprintf(writer, "This guy named %s, was coming from %s .", name, country) }
router.go
:
package main import ( "github.com/gorilla/mux" ) func RegisterRoutes(r *mux.Router) { indexRouter := r.PathPrefix("/index").Subrouter() indexRouter.Handle("/", &HelloHandler{}) userRouter := r.PathPrefix("/user").Subrouter() userRouter.HandleFunc("/names/{name}/countries/{country}", ShowVisitorInfo) }
在router.go
中咱們將路由分爲index
和user
兩組,在兩個路由組上分別定義路由。將這部分封裝在一個導出函數RegisterRoutes
供調用。這樣即便之後路由註冊的程序要放到單獨的目錄裏也能夠供外部調用。
整理完後咱們的main.go
中就會變的很簡潔:
func main() { //mux := http.NewServeMux() //mux.Handle("/", &helloHandler{}) muxRouter := mux.NewRouter() RegisterRoutes(muxRouter) server := &http.Server{ Addr: ":8080", Handler: muxRouter, } ...... err := server.ListenAndServe() ...... }
關注公衆號回覆go-http-02
獲取本文中完整的示例代碼。
前文回顧:深刻學習用 Go 編寫HTTP服務器
喜歡個人文章,幫忙轉發點贊,如在實踐過程當中遇到什麼問題可在下方給我留言。