对于Golang来说,实现一个简单的http服务器<代码> 代码>非常容易,只需要短短几行代码。同时有了协程的加持,去实现的<代码> http服务器> 代码能够取得非常优秀的性能。这篇文章将会对去标准库<代码>net/http 代码>实现http服务的原理进行较为深入的探究,以此来学习了解网络编程的常见范式以及设计思路。
基于HTTP构建的网络应用包括两个端,即客户端(<代码>客户端> 代码)和服务端(服务器<代码> 代码>)。两个端的交互行为包括从客户端发出<代码> 代码>请求,服务端接受<代码> 代码>请求进行处理并返回<代码> 代码>以响应及客户端处理<代码>反应> 代码。所以HTTP服务器的工作就在于如何接受来自客户端的<代码> 代码>请求,并向客户端返回响应代码> <代码>。
典型的http服务端的处理流程可以用下图表示:
服务器在接收到请求时,首先会进入路由路由器(<代码> 代码>),这是一个<代码>多路复用器> 代码,路由的工作在于为这个<代码> 代码>找请求到对应的处理器(<代码>处理程序> 代码),处理器对请求<代码> 代码>进行处理,并构建<代码> 代码>反应.Golang实现的<代码> http服务器代码>同样遵循这样的处理流程。
我们先看看Golang如何实现一个简单的http服务器代码>:<代码>
主要包 导入( “fmt” “net/http” ) func indexHandler http (w。ResponseWriter r * http.Request) { fmt。流(w,“hello world”) } 函数main () { http。indexHandler HandleFunc (“/? http。nil ListenAndServe (“8000”) }
运行代码之后,在浏览器中打开<代码> localhost: 8000> 代码就可以看到<代码> hello world> 代码。这段代码先利用<代码> http。HandleFunc> 代码在根路由<代码>/代码>上注册了一个<代码> indexHandler> 代码,然后利用<代码> http。ListenAndServe 代码>开启监听。当有请求过来时,则根据路由执行对应的<代码>处理程序> 代码函数。
我们再来看一下另外一种常见的http服务器<代码> 代码>实现方式:
主要包 导入( “fmt” “net/http” ) indexHandler struct类型{ 内容的字符串 } func (ih * indexHandler) ServeHTTP http (w。ResponseWriter r * http.Request) { fmt。流(w, ih.content) } 函数main () { http。处理(“/?indexHandler{内容:“hello world !”}) http。nil ListenAndServe (“8001”) }
去实现的http代码> <代码>服务步骤非常简单,首先注册路由,然后创建服务并开启监听即可。下文我们将从注册路由,开启服务,处理请求这几个步骤了解Golang如何实现<代码> http 代码>服务。
<代码> http。HandleFunc 代码>和<代码> http。处理> 代码都是用于注册路由,可以发现两者的区别在于第二个参数,前者是一个具有<代码> func (w http。ResponseWriter r * http.Requests) 代码>签名的函数,而后者是一个结构体,该结构体实现了<代码> func (w http。ResponseWriter r * http.Requests) 代码>签名的方法。
<代码> http。HandleFunc 代码>和<代码> http。处理> 代码的源码如下:
func HandleFunc(模式字符串处理函数(ResponseWriter, *请求)){ DefaultServeMux。HandleFunc(模式,处理程序) }//HandleFunc注册处理程序函数给定的模式。 func (mux * ServeMux) HandleFunc(模式字符串处理函数(ResponseWriter, *请求)){ 如果处理程序==nil { 恐慌(“http:零处理程序”) } mux。处理(模式,HandlerFunc(处理器)) }
函数处理(模式字符串处理程序处理程序){ DefaultServeMux。处理(模式,处理程序) }
可以看到这两个函数最终都由<代码> DefaultServeMux> 代码调用<代码> 代码>处理方法来完成路由的注册。
这里我们遇到两种类型的对象:<代码> ServeMux 代码>和<代码>处理程序> 代码,我们先说<代码>处理程序代码>。
代码> <代码>处理程序是一个接口:
类型的处理程序接口{ ServeHTTP (ResponseWriter *请求) }深入理解Golang之http服务器的实现