关于Go的http.HandleFunc
方法执行过程
http.HandleFunc
方法作用为注册请求URL到具体处理方法的映射,也就是方法的路由。
首先贴上方法原型
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))
}
// ServeMux.Handle 方法定义
func (mux *ServeMux) Handle(pattern string, handler Handler)
直接调用了默认路由的HandleFunc
方法,在HandleFunc
方法中,首先进行判空,然后调用了ServeMux
的Handle
方法,这个Handle
方法传入了两个参数,一个是我们需要匹配的URL
,一个是Handler。
但是我们根据代码可以看到,并没有传入方法需要的Handler
,而是将我们的func
进行了一次类型强转,把Handler
转成了HandlerFunc
,Handler
和HandlerFunc
定义如下:
// Handler接口定义
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
// HandlerFunc 类型定义
// The HandlerFunc type is an adapter to allow the use of
// ordinary functions as HTTP handlers. If f is a function
// with the appropriate signature, HandlerFunc(f) is a
// Handler that calls f.
type HandlerFunc func(ResponseWriter, *Request)
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
可以看到,Hander
是一个接口,接口中定义了一个ServeHTTP
方法,这个方法也就是当请求过来时,将被转发调用的方法。
而HandlerFunc
是一种函数类型,同时实现了ServeHTTP
这个方法,由于它本身是函数类型,因此能对自身进行了调用,而这个"自身"实际上就是我们路由处理所绑定的方法,在实现过程中,就对自身进行了调用。因此整个过程便明了。
最终的ServeMux.Handle
方法便是将具体的Url
通过一个map
与相对应的Handler
所绑定,具体实现如下:
if mux.m == nil {
mux.m = make(map[string]muxEntry)
}
e := muxEntry{h: handler, pattern: pattern}
mux.m[pattern] = e
当请求过来时,通过路由规则,找到相对应的Handler,执行ServeHTTP
方法,此时将调用HandlerFunc.ServeHTTP
,在其实实现中将会对本身类型进行调用,即f(w, r)
,最终调用到我们所绑定的方法。