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的类型。
到这里可以看出来,流程是
- mux.HandleFunc("/",hello)
- mux.Handle(pattern, HandlerFunc(handler))
- 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函数了。