关于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方法中,首先进行判空,然后调用了ServeMuxHandle方法,这个Handle方法传入了两个参数,一个是我们需要匹配的URL,一个是Handler。

但是我们根据代码可以看到,并没有传入方法需要的Handler,而是将我们的func进行了一次类型强转,把Handler转成了HandlerFuncHandlerHandlerFunc定义如下:

// 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),最终调用到我们所绑定的方法。

Last modification:May 19, 2022
If you think my article is useful to you, please feel free to appreciate