一文读懂 Go Http Server 原理

俗话说万事开头难,但用 Go 实现一个 Http Server 真不难,简单到什么程度?起一个 Server,并且能响应请求,算上包名、导入的依赖,甚至空行,也就只要 15 行代码:,这么简单,能与之一战的恐怕只有 Python 了吧,而且 Go 还能编译成可执行的二进制文件,你说牛啤不牛啤?,我们从这一行代码看起,从命名来看,这个方法干了两件事,监听并且服务,从方法的单一职责上来说,我觉得不ok,一个方法怎么能干两件事?但这是大佬写的代码,就很合理。,第一个参数Addr是要监听的地址和端口,第二个参数Handler一般是nil,它是真正的逻辑处理,但我们通常用第一行代码那样来注册处理器,这代码一看就感觉是把 path 映射到业务逻辑上,我们先大概了解,待会再来看它。,如果了解过一点网络编程基础,就会知道操作系统提供了bind、listen、accept这样的系统调用,我们只要按顺序发起调用,就能组合出一个 Server。,Go 也是利用这些系统调用,把他们都封装在了ListenAndServe中。,图片,Listen 往下追究就是系统调用,所以我们重点看 Serve:,图片,把分支代码收起来,只看主干,发现是一个 for 循环里面在不停地 Accept,而这个 Accept 在没有连接时是阻塞的,当有连接时,起一个新的协程来处理。,处理请求的一行代码是,可以看出是每个连接单开了一个协程处理:,这里的 connCtx 代入了当前的 Server 对象:,而且还提供了修改它的 hook 方法 srv.ConnContext,可以在每次 Accept 时修改原始的 context,它的定义是:,但是如果按照我开头给的代码,你是没法修改 srv.ConnContext 的,可以改成这样来自定义:,同样的 c.setState 也提供了 hook,可采取如上的方法设置,在每次连接状态改变时执行 hook 方法:,为了能看清楚 Accept 后,serve 方法到底干了什么,我们再简化一下:,serve 也是一个大循环,循环里面主要是读取一个请求,然后将请求交给 Handler 处理。,为什么是一个大循环呢?因为每个 serve 处理的是一个连接,一个连接可以有多次请求。,读请求就显得比较枯燥乏味,按照Http协议,读出URL,header,body等信息。,这里有个细节是在每次读取了一个请求后,还开了一个协程去读下一个请求,也算是做了优化吧。,当读取到一个请求后,便进入这一行代码:,ServeHTTP 找到我们注册的 Handler 去处理,如果请求的URI 是 *或请求 Method 是 OPTIONS,则使用globalOptionsHandler,也就是说这类请求不需要我们手动处理,直接就返回了。,对于我们注册的 Handler 也需要去寻找路由,这个路由的规则还是比较简单,主要由如下三条:,举几个例子来理解一下:,注册路由为,此时如果执行,则会匹配到 hello2,但如果执行,就匹配的是 hello,如果注册路由为,注意第二个最后还有个/,此时如果执行,也能匹配到 hello2,怎么样,是不是理解了?,找到路由之后就直接调用我们开头注册的方法,如果我们往 Response 中写入数据,就能返回给客户端,这样一个请求就处理完成了。,最后我们回忆下 Go Http Server 的要点:,
,图片,

文章版权声明

 1 原创文章作者:cmcc,如若转载,请注明出处: https://www.52hwl.com/17563.html

 2 温馨提示:软件侵权请联系469472785#qq.com(三天内删除相关链接)资源失效请留言反馈

 3 下载提示:如遇蓝奏云无法访问,请修改lanzous(把s修改成x)

 免责声明:本站为个人博客,所有软件信息均来自网络 修改版软件,加群广告提示为修改者自留,非本站信息,注意鉴别

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023年3月5日 上午12:00
下一篇 2023年3月7日 下午10:34