mux简介
mux implement了一个请求路由器和调度符合要求的输入请求到相应的视图函数中,mux是http request multiplexer 就是http多路复用器
mux的特点是
- implement了http.Handler接口 因此跟http.ServeMux是兼容的
- 请求可以基于URL path path前缀 协议 头部 还有请求参数 http方法 或者使用客制的匹配器
- URL host, path 还有query values可以使用正则表达式来匹配变量
- 注册URL可以被构造 或者”反向” 这样有助于维护队资源的引用
- 可以使用子路由 嵌套路由只有当父路由被匹配之后才会被指向 有利于路由的分类 以及在视图函数的编写上遵循模块化编程的准则
install
go get -u github.com/gorilla/mux
hello world
1 | package main |
基本使用
声明一个路由
r := mux.NewRouter()
注册视图函数1
2
3r.HandleFunc("/products/{key}", ProductHandler)
r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler)
r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler)
注意到上面的URL匹配那里是可以使用正则表达式来进行匹配变量的
视图函数编写1
2
3
4
5func ArticlesCategoryHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, "Category: %v\n", vars["category"])
}
视图函数或者说handler都是两个默认参数
- w http.ResponseWriter
- r *http.Request
要注意第二http.request请求的参数指针类型的 不要写错 其它跟Java的servlet基本相同 使用writer讲返回内容输出到http response中 但是要注意视图函数都是void类型 没有返回值
路由匹配
匹配域名
r.Host("www.example.com")
匹配一个动态的子域名 可以使用正则
r.Host("{subdomain:[a-z]+}.domain.com")
匹配URL前缀
r.PathPrefix("/products/")
匹配http方法
r.Methods("GET", "POST")
匹配协议
r.Schemes("https")
匹配头部
r.Headers("X-Requested-With", "XMLHttpRequest")
匹配查询参数
r.Queries("key", "value")
使用客制匹配器1
2
3r.MatcherFunc(func(r *http.Request, rm *RouteMatch) bool {
return r.ProtoMajor == 0
})
上面的各种匹配是可以一起声明的 向下面这样1
2
3
4r.HandleFunc("/products", ProductsHandler).
Host("www.example.com").
Methods("GET").
Schemes("http")
mux路由匹配冲突问题
如果一个请求跟两个路由都匹配 这就造成了冲突 这时候第一个会被成功匹配
子路由
子路由不仅仅很方便 而且有利于优化代码
例子1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28package main
import (
"github.com/gorilla/mux"
"net/http"
"log"
)
func test(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("lalalala"))
w.WriteHeader(http.StatusOK)
}
func testSubRouter(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("this is subrouter page"))
vars := mux.Vars(r)
key := vars["key"]
w.Write([]byte(key))
w.WriteHeader(http.StatusOK)
}
func main() {
r := mux.NewRouter()
s := r.PathPrefix("/hello").Subrouter()
s.HandleFunc("/{key}", testSubRouter)
r.HandleFunc("/test", test)
log.Fatal(http.ListenAndServe("localhost:8080", r))
}
静态文件
静态文件在mux中一般使用static的url前缀来匹配 这样非常方便
未完待续!