Golang | HttpRouter

_Liu_ · · 2444 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

1、什么是httprouter

httprouter谈不上是一个框架,它的性能非常优秀。完全可以用来代替默认的 ServeMux

所以比较适合对性能要求高,路由相对简单扁平的业务,或者作为高层HTTP框架的内部模块。

httproute内部通过实现一个trie树来提高性能。

核心代码就是golang标准库中 http.Handler 接口,在该函数中实现自己的请求路由分发策略。

gorilla/mux也是一个第三方的路由器,但是性能一般

2、为什么用httprouter

说说net/http的不足:
  • 不能单独的对请求方法(POST,GET等)注册特定的处理函数
  • 不支持路由变量参数
  • 不能自动对Path进行校准
  • 性能一般、扩展性不足
httprouter带来哪些便利?
  • 仅支持精确匹配,及只匹配一个模式或不会匹配到任何模式。相对于其他一些mux,例如go原生的 http.ServerMux, 会使得一个请求URL匹配多个模式,从而需要有优先级顺序,例如最长匹配、最先匹配等等。
  • 不需要关心URL结尾的斜杠
  • 路径自动归一化和矫正
  • 零内存分配、高性能

3、httprouter路由匹配

net/http的路由匹配
//	/api,可以访问到
//	/api/,不可以
http.HandleFunc("/api",func(w http.ResponseWriter,r *http.Request){
	fmt.Println("/api")
})

//	/api,可以
//	/api/,也可以
http.HandleFunc("/api/",func(w http.ResponseWriter,r *http.Request){
	fmt.Println("/api")
})
复制代码
httprouter的路径匹配规则

两个路由命名捕获方式:(==路由命名的捕获,不是路由参数的捕获==)

  • :name named parameter (只能根据路由命名进行捕获)
  • *name catch-all parameter (*表示捕获任意内容)

其中:name的捕获方式是匹配内容直到下一个斜线或者路径的结尾。例如要为如下路径注册 handler:

Path: /blog/:category/:post  
router.GET("/blog/:category/:post", Hello) //(category/post可以看成是一个变量)
	
当请求路径为:
/blog/go/request-routers            match: category="go", post="request-routers"
/blog/go/request-routers/           no match, but the router would redirect
/blog/go/                           no match
/blog/go/request-routers/comments   no match
复制代码

*name的捕获方式是从指定位置开始 (包含前缀 "/") 匹配到结尾:

Path: /files/*filepath     */
router.GET("/files/*filepath", Hello) //filepath可以看成是一个变量

当请求路径为:
/files/                             match: filepath="/"
/files/LICENSE                      match: filepath="/LICENSE"
/files/templates/article.html       match: filepath="/templates/article.html"
/files                              no match, but the router would redirect
复制代码

4、httprouter重定向

func New() *Router {
	return &Router{
		//是否启用自动重定向。
        //比如请求/foo/,但是只有/foo的handler,则httprouter内部使用301重定向到/foo进行GET处理。
        //查看浏览器可以看到301的请求,可以看到请求头的location:/foo
        
        //直接get,然后响应一个字符串,这里的文本类型是text/plain,其实就是txt文件
        //这也就为什么,只有/foo的handler时,请求/foo/会404,因为/foo/代表着foo目录,默认会请求/foo/index.html,不就404了
        RedirectTrailingSlash:  true,
        
	RedirectFixedPath:      true,
		
        HandleMethodNotAllowed: true,
		
        //如果启用,则路由器会自动回复OPTIONS请求
        HandleOPTIONS:          true,
	}
}
复制代码

5、lookup

func (r *Router) Lookup(method, path string) (Handle, Params, bool)
复制代码

Lookup根据method+path检索对应的Handle,以及Params,并可以通过第三个返回值判断是否会进行重定向。

6、关于参数

除了路由参数,还有URL的query参数,也就是?a=b&c=d这样的格式

query参数
//url参数解析
http.HandleFunc("/api/", func(w http.ResponseWriter, r *http.Request) {
    values := r.URL.Query()
    fmt.Println(values)
})

//result
//http://127.0.0.1:9090/api/?a=1&b=2&c=3
//map[a:[1] b:[2] c:[3]]
复制代码
路由参数
//使用场景有哪些呢??
/users/123
/users/456
/users/23456
比如有很多用户,如上,我们需要为一个个用户去注册路由?显然不现实
这时就可以使用路由参数了,/users/id
复制代码

有疑问加站长微信联系(非本文作者)

本文来自:掘金

感谢作者:_Liu_

查看原文:Golang | HttpRouter

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2444 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传