深入理解Golang之http server的实现

2020-01-28 14:26:07王旭
func(w http.ResponseWriter, r *http.Requests) 签名的函数,而后者是一个结构体,该结构体实现了 func(w http.ResponseWriter, r *http.Requests) 签名的方法。

http.HandleFunchttp.Handle 的源码如下:


func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
 DefaultServeMux.HandleFunc(pattern, handler)
}

// HandleFunc registers the handler function for the given pattern.
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
 if handler == nil {
  panic("http: nil handler")
 }
 mux.Handle(pattern, HandlerFunc(handler))
}

func Handle(pattern string, handler Handler) { 
 DefaultServeMux.Handle(pattern, handler)
}

可以看到这两个函数最终都由 DefaultServeMux 调用 Handle 方法来完成路由的注册。

这里我们遇到两种类型的对象: ServeMuxHandler ,我们先说 Handler

Handler

Handler 是一个接口:


type Handler interface {
 ServeHTTP(ResponseWriter, *Request)
}

Handler 接口中声明了名为 ServeHTTP 的函数签名,也就是说任何结构只要实现了这个 ServeHTTP 方法,那么这个结构体就是一个 Handler 对象。其实go的 http 服务都是基于 Handler 进行处理,而 Handler 对象的 ServeHTTP 方法也正是用以处理 request 并构建 response 的核心逻辑所在。

回到上面的 HandleFunc 函数,注意一下这行代码:


mux.Handle(pattern, HandlerFunc(handler))

可能有人认为 HandlerFunc 是一个函数,包装了传入的 handler 函数,返回了一个 Handler 对象。然而这里 HandlerFunc 实际上是将 handler 函数做了一个 类型转换 ,看一下 HandlerFunc 的定义:


type HandlerFunc func(ResponseWriter, *Request)

// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
 f(w, r)
}

HandlerFunc 是一个类型,只不过表示的是一个具有 func(ResponseWriter, *Request) 签名的函数类型,并且这种类型实现了 ServeHTTP 方法(在 ServeHTTP 方法中又调用了自身),也就是说这个类型的函数其实就是一个 Handler 类型的对象。利用这种类型转换,我们可以将一个 handler 函数转换为一个

Handler 对象,而不需要定义一个结构体,再让这个结构实现 ServeHTTP 方法。读者可以体会一下这种技巧。