golang自带的http.SeverMux路由实现简单,本质是一个map[string]Handler,是请求路径与该路径对应的处理函数的映射关系。实现简单功能也比较单一: 1. 不支持正则路由, 这个是比较致命的 2. 只支持路径匹配,不支持按照Method,header,host等信息匹配,所以也就没法实现RESTful架构 而gorilla/mux是一个强大的路由,小巧但是稳定高效,不仅可以支持正则路由还可以按照Method,header,host等信息匹配,可以从我们设定的路由表达式中提取出参数方便上层应用,而且完全兼容http.ServerMux
Router的实现 路由信息是存放在一个Route类型的数组([]Route)中,数组中的每一个Route对象都表示一条路由信息,其中包含匹配该路由应该满足的所有条件及对应的上层处理Hanlder。当请求到来是Router会遍历Route数组,找到第一个匹配的路由则执行对应的处理函数,如果找不到则执行NotFoundHandler。
Route的实现 Route的实现其实也比较简单,正则表达式的解析不太好理解,subrouter的实现更是需要好好研究代码,但是这些对理解Route的设计思路实现影响不大。每一个Route中包含一个matcher数组,是所有限定条件的集合,matcher是一个返回bool值的接口。 当我们添加路由限定条件时,就是往matcher数组中增加一个限定函数。 当请求到来时,Route.Match()会遍历matcher数组,只有数组中所有的元素都返回true时则说明此请求满足该路由的限定条件。 假设我们规定只能以GET方式访问/user/{userid:[0-9]+}并且header中必须包含“Refer”:”example.com”,才能得到我们想要的结果我们可以这样设置路由
然后我们来看下Route是如何保存这三个限定条件的
上面三个限定条件是如何实现的已经分析完了,路径匹配的最终正则表达式是/user/([0-9]+),参数名”userid”保存在varsN数组中,当正则匹配时提取出正则表达式中的参数值,并与varsN数组中的参数名称做关联,建立一个map[string][string]{“userid”:”123456”}
因为gorilla/mux选择与http.ServerMux的接口保持一致,所以上层应用的处理函数也就变成了固定的 Hanlder
正则匹配解析出的参数Vars怎么传递给上层处理函数呢?gorilla/mux使用了一个第三方模块gorilla/context。当http请求到来时,mux.Router会选择合适的路由,并提取出一些参数信息,将这些参数信息与http.Request对象在gorilla/context中建立映射关系,上层处理函数根据http.Request对象到context中找到该http.Request所对应的参数信息。 context的实现如下
上层处理函数中调用mux.Vars(r)则可以取出该http.Request所关联的参数信息
转自:http://shanks.leanote.com/post/gorilla-mux%E7%B1%BB%E5%BA%93%E8%A7%A3%E6%9E%90