今天这篇文章咱们将会为咱们以前编写的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服务器
喜欢个人文章,帮忙转发点赞,如在实践过程当中遇到什么问题可在下方给我留言。