Go语言经典库使用分析(七)

Go语言(golang)的一个很大的优势,就是很容易的开发出网络后台服务,而且性能快,效率高。在开发后端HTTP网络应用服务的时候,我们需要处理很多HTTP的请求访问,比如常见的API服务,我们就要处理很多HTTP请求,然后把处理的信息返回给使用者。对于这类需求,Golang提供了内置的包帮我们来处理这些HTTP请求,让我们可以比较方便的开发一个HTTP服务。

net/http

这是包中一个经典的HTTP服务实现,我们运行后打开,就可以看到如下信息:

显示的关键就是我们函数,我们通过该函数注册了对路径的处理函数,所有才会看到上面的显示信息。那么这个他是如何注册函数的呢?下面看看这个函数的源代码。

看以上的源代码,是存在一个默认的路由的,这个类型是,我们注册的路径函数信息都被存入的字段中,以便处理HTTP请求的时候使用。

函数最终会调用函数。

这下应该明白了,注册的路径和相应的处理函数都存入了m字段中。

既然注册存入了相应的信息,那么在处理HTTP请求的时候,就可以使用了。Go语言的更底层细节就不详细分析了,我们只要知道处理HTTP请求的时候,会调用接口的方法,而正好实现了。

上面代码中的会获取到我们注册的函数,然后执行它,具体的详细实现不再分析了,大家可以自己看下源代码。

现在我们可以总结下包对HTTP请求的处理。

这就是整个一条请求处理链,现在我们明白了里对HTTP请求的原理。

net/http 的不足

我们自己在使用内置的的默认路径处理HTTP请求的时候,会发现很多不足,比如:

不能单独的对请求方法(POST,GET等)注册特定的处理函数

不支持Path变量参数

不能自动对Path进行校准

性能一般

扩展性不足

……

那么如何解决以上问题呢?一个办法就是自己写一个处理HTTP请求的路由,因为从上面的源代码我们知道,用的是默认的路径。

通过以上的代码分析,我们自己在通过函数启动一个HTTP服务的时候,最后一个的值是nil,所以上面的nil判断成立,使用的就是默认的路由。

现在我们就知道如何使用自己定义的路由了,那就是给的最后一个参数传一个自定义的路由,比如:

这个自定义的就是我们的路由,它显示了和使用演示的例子一样的功能。

现在我们改变下代码,只有方法才会显示以上信息。

只需要改变下方法的处理逻辑即可,现在我们可以换不同的请求方法试试,就会显示不同的内容。

这个就是自定义,我们可以通过扩展方法的实现来添加我们想要的任何功能,包括上面章节列出来的的不足都可以解决,不过我们无需这么麻烦,因为开源大牛已经帮我们做了这些事情,它就是 github.com/julienschmidt/httprouter

httprouter

httprouter 是一个高性能、可扩展的HTTP路由,上面我们列举的默认路由的不足,都被httprouter 实现,我们先用一个例子,认识下 httprouter 这个强大的 HTTP 路由。

这个例子,实现了在请求路径时,会显示如下信息:

在这个例子中,首先通过生成了一个路由指针,然后使用方法注册一个适配路径的函数,最后作为参数传给函数启动HTTP服务即可。

其实不止是方法,httprouter 为所有的HTTP Method 提供了快捷的使用方式,只需要调用对应的方法即可。

以上这些方法都是 httprouter 支持的,我们可以非常灵活的根据需要,使用对应的方法,这样就解决了默认路由的问题。

httprouter 命名参数

现代的API,基本上都是Restful API,httprouter提供的命名参数的支持,可以很方便的帮助我们开发Restful API。比如我们设计的API,这这样一个URL,可以查看这个用户的信息,如果要查看其他用户的,比如,我们只需要访问API即可。

现在我们可以发现,其实这是一种URL匹配模式,我们可以把它总结为,这是一个通配符,看个例子。

当我们运行,在浏览器里输入时,就会显示.

通过上面的代码示例,可以看到,路径的参数是以开头的,后面紧跟着变量名,比如,然后在这个处理函数中,通过的获取对应的值。

这种匹配模式,是精准匹配的,同时只能匹配一个,比如:

因为httprouter这个路由就是单一匹配的,所以当我们使用命名参数的时候,一定要注意,是否有其他注册的路由和命名参数的路由,匹配同一个路径,比如这个路由和就是冲突的,不能同时注册。

这里稍微提下httprouter的另外一种通配符模式,就是把换成,也就是,这是一种匹配所有的模式,不常用,比如:

因为是匹配所有的模式,所以只要前面的路径匹配,就是匹配的,不管路径多长,有几层,都匹配。

httprouter兼容http.Handler

通过上面的例子,我们应该已经发现,方法的handle,并不是我们熟悉的,它是httprouter自定义的,相比多了一个通配符参数的支持。

自定义的Handle,唯一的目的就是支持通配符参数,如果你的HTTP服务里,有些路由没有用到通配符参数,那么可以使用原生的,httprouter是兼容支持的,这也为我们从的方式,升级为httprouter路由提供了方便,会高效很多。

httprouter通过和两个函数,提供了兼容和的完美支持。从以上源代码中,我们可以看出,实现的方式也比较简单,就是做了一个到的转换,舍弃了通配符参数的支持。

Handler处理链

得益于的模式,我们可以把不同的组成一个处理链,也是实现了的,所以它也可以作为处理链的一部分,比如和、这两个库配合使用,关于这两个库的介绍,可以参考我以前写的文章。

这里使用一个官方的例子,作为Handler处理链的演示。

比如对多个不同的二级域名,进行不同的路由处理。

以上就是一个简单的,针对不同域名,使用不同路由的例子,代码中的注释比较详细了,这里就不一一解释了。这个例子中,和这两个就组成了一个处理链。

httprouter 静态文件服务

httprouter提供了很方便的静态文件服务,可以把一个目录托管在服务器上,以供访问。

只需要这一句核心代码即可,这个就是把当前目录托管在服务器上,以供访问,访问路径是。

使用需要注意的是,第一个参数路径,必须要以,因为要获取我们要访问的路径信息。

这是源代码实现,我们发现,最后还是一个请求服务,通过把的路径的内容显示出来(如果路径是个目录则列出目录文件;如果路径是文件,则显示内容)。

通过上面的源代码,我们也可以知道,这个通配符是为了获取要放问的文件路径,所以要符合预定,不然就会panic。

httprouter 异常捕获

很少有路由支持这个功能的,httprouter允许使用者,设置用于处理HTTP请求中发生的panic。

演示例子中,我们通过设置来处理发生的panic,处理办法是打印出来异常信息。然后故意在函数中抛出一个painc,然后我们运行测试,会看到异常信息。

这是一种非常好的方式,可以让我们对painc进行统一处理,不至于因为漏掉的panic影响用户使用。

小结

httprouter还有不少有用的小功能,比如对404进行处理,我们通过设置来实现,我们看看这个结构体的配置,可以发现更多有用的功能。

这些字段都是导出的(export),我们可以直接设置,来达到我们的目的。

httprouter是一个高性能,低内存占用的路由,它使用radix tree实现存储和匹配查找,所以效率非常高,内存占用也很低。关于radix tree大家可以查看相关的资料。

httprouter因为实现了,所以可扩展性非常好,可以和其他库、中间件结合使用,gin这个web框架就是使用的自定义的httprouter。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190107B060T800?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券