golang HandleFunc的调用

func hello(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w,"hello web")
}
func main(){
        mux := http.NewServeMux()
    mux.HandleFunc("/",hello)   

    server := &http.Server{
        Addr: ":8080",
        Handler:mux,
    }

    if err := server.ListenAndServe(); err != nil{
        log.Fatal(err)
    }
}

用HandleFunc 注册了一个路径,当访问127.0.0.1:8080的时候 是怎么回调到hello这个函数的呢?

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

HandleFunc的原型。当我们调用HanldeFunc("/",hello)的时候 会进入这里调用mux.Handle(pattern,HandleFunc(handler))

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

type HandlerFunc func(ResponseWriter, *Request)

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

从代码中可以看出来,ServHttp是一个接口,HandlerFunc实现了这个接口,HandlerFunc的类型就是我们外边hello的类型。
到这里可以看出来,流程是

  1. mux.HandleFunc("/",hello)
  2. mux.Handle(pattern, HandlerFunc(handler))
  3. f(w, r)
    这里f(w,r)相当于是一个回调,当执行ServeHTTP的时候会执行f(w,r) 。 f(w,r)就是我们自己封装的 func hello的回调
    那么ServeHTTP在哪儿执行呢
    我们看 server.ListenAndServe();
    ListenAndSeerve的原型
func (srv *Server) ListenAndServe() error {
    if srv.shuttingDown() {
        return ErrServerClosed
    }
    addr := srv.Addr
    if addr == "" {
        addr = ":http"
    }
    ln, err := net.Listen("tcp", addr)
    if err != nil {
        return err
    }
    return srv.Serve(ln)
}

接着往里走 srv.Serve(ln)
由于Serve代码太多我只写关键部分

func (srv *Server) Serve(l net.Listener) error {
  ......
  go c.serve(ctx)
}
//c.serve 继续往里走
func (c *conn) serve(ctx context.Context) {
    ......
    serverHandler{c.server}.ServeHTTP(w, w.req)
}
//ServeHTTP 的原型
func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
    handler := sh.srv.Handler
    if handler == nil {
        handler = DefaultServeMux
    }
    if req.RequestURI == "*" && req.Method == "OPTIONS" {
        handler = globalOptionsHandler{}
    }
    handler.ServeHTTP(rw, req)
}

当进入handler.ServeHTTP的时候,就进入
我们之前写的

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

看到f(w,r) 就看到了我们定义的hello函数了。

你可能感兴趣的:(golang HandleFunc的调用)