Example
package mainimport ("fmt""log""net/http")func sayHello(w http.ResponseWriter, r *http.Request) {fmt.Fprintf(w, "Hello World!")}func main() {http.HandleFunc("/", sayHello)err := http.ListenAndServe(":9090", nil)if err != nil {log.Fatal("ListenAndServe: ", err)}}
Execute Flow
http.HandleFunc
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {DefaultServeMux.HandleFunc(pattern, handler)}func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {if handler == nil {panic("http: nil handler")}mux.Handle(pattern, HandlerFunc(handler))}func (mux *ServeMux) Handle(pattern string, handler Handler) {mux.mu.Lock()defer mux.mu.Unlock()...if mux.m == nil {mux.m = make(map[string]muxEntry)}e := muxEntry{h: handler, pattern: pattern}mux.m[pattern] = eif pattern[len(pattern)-1] == '/' {mux.es = appendSorted(mux.es, e)}if pattern[0] != '/' {mux.hosts = true}}func appendSorted(es []muxEntry, e muxEntry) []muxEntry {n := len(es)i := sort.Search(n, func(i int) bool {return len(es[i].pattern) < len(e.pattern)})if i == n {return append(es, e)}// we now know that i points at where we want to insertes = append(es, muxEntry{}) // try to grow the slice in place, any entry works.copy(es[i+1:], es[i:]) // Move shorter entries downes[i] = ereturn es}
type ServeMux struct {mu sync.RWMutexm map[string]muxEntryes []muxEntry // slice of entries sorted from longest to shortest.hosts bool // whether any patterns contain hostnames}type muxEntry struct {h Handlerpattern string}var DefaultServeMux = &defaultServeMuxvar defaultServeMux ServeMux
按顺序做了几件事:
- 调用了 DefaultServerMux 的 HandleFunc
- 调用了 DefaultServerMux 的 Handle
- 往 DefaultServeMux 的 map[string]muxEntry 中增加对应的 handler 和路由规则
直接调用 HandleFunc ,会间接调用 mux.HandleFunc ,之后 mux.Handle() 将传入的 handler 强制转换为 HandlerFunc 类型,故而实现了 Handler 接口。http.ListenAndServe 参数中的 handler 通常为 nil,在这种情况下使用 DefaultServeMux。
http.ListenAndServe
mux.ServeHTTP
按顺序做了几件事:
- 实例化 Server
2. 调用 net.Listen("tcp", addr)监听端口
- 启动一个 for 循环,在循环体中 Accept 请求
- 对每个请求实例化一个 Conn,并且开启一个 goroutine 为这个请求进行服务 go c.serve()
- 启动一个 for 循环,在循环体中读取每个请求的内容 w, err := c.readRequest()
进入 serverHandler.ServeHTTP ,判断 handler 是否为空,为空就将 handler 设置为 DefaultServeMux
调用相应 handler 的 ServeHTTP,在这个例子中,下面就进入到 DefaultServeMux.ServeHTTP
- 进入 mux.ServeHTTP, 调用 mux.Handler ,根据 request 选择 handler
- 选择 handler:
- 判断是否有路由能满足这个 request (循环遍历 ServerMux 的 muxEntry)
- 如果有路由满足,调用这个路由 handler 的 ServeHTTP
- 如果没有路由满足,调用 NotFoundHandler 的 ServeHTTP
- 进入到这个 handler 的 ServeHTTP,即执行 mux.Handler(r).ServeHTTP(w, r)
Trick
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)}
将这一段专门摘出来,分析它们之间的关系。这里将 HandlerFunc 定义为一个函数类型,因此以后当调用 HandlerFunc(f) 之后, f 就会成为 HandlerFunc 类型,同时实现了Handler 接口,并且调用 ServeHttp 方法实际上就是调用 f 的对应方法
