func(w http.ResponseWriter, r *http.Requests) 签名的函数,而后者是一个结构体,该结构体实现了 func(w http.ResponseWriter, r *http.Requests) 签名的方法。
http.HandleFunc 和 http.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 方法来完成路由的注册。
这里我们遇到两种类型的对象: ServeMux 和 Handler ,我们先说 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 方法。读者可以体会一下这种技巧。









