這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
這裡我們分析預設的Handler–DefaultServeMux
在所有介紹之前,我們先給出兩個類:
type ServeMux struct { mu sync.RWMutex m map[string]muxEntry hosts bool // whether any patterns contain hostnames}type muxEntry struct { explicit bool h Handler pattern string}
ServeMux實現了Handler借口的ServeHTTP函數;我們知道GO語言中,實現了介面的所有函數,則實現該介面
// ServeHTTP dispatches the request to the handler whose// pattern most closely matches the request URL.func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) { if r.RequestURI == "*" { if r.ProtoAtLeast(1, 1) { w.Header().Set("Connection", "close") } w.WriteHeader(StatusBadRequest) return } h, _ := mux.Handler(r) h.ServeHTTP(w, r)}
。接著我們繼續DefaultServeMux,我們在上篇的例子中雖然沒有傳入Handler對象,但是我們有這樣一行代碼:
http.HandleFunc("/hello", SayHello)
其實這行代碼操作的就是預設的Handler對象DefaultServeMux,為特定的URL設定處理函數。我們看下該函數,具體做了哪些操作:
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) { DefaultServeMux.HandleFunc(pattern, handler)}
簡單粗暴,直接就是調用DefaultServeMux對象的HandleFunc函數,其實DefaultServeMux是一個ServeMux對象:
// NewServeMux allocates and returns a new ServeMux.func NewServeMux() *ServeMux { return &ServeMux{m: make(map[string]muxEntry)} }// DefaultServeMux is the default ServeMux used by Serve.var DefaultServeMux = NewServeMux()
DefaultServeMux對象的HandleFunc函數,也即ServeMux的成員函數:
// HandleFunc registers the handler function for the given pattern.func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) { mux.Handle(pattern, HandlerFunc(handler))}
該函數是Handle(pattern, HandlerFunc(handler))的封裝:
// Handle registers the handler for the given pattern.// If a handler already exists for pattern, Handle panics.func (mux *ServeMux) Handle(pattern string, handler Handler) { mux.mu.Lock() defer mux.mu.Unlock() if pattern == "" { panic("http: invalid pattern " + pattern) } if handler == nil { panic("http: nil handler") } if mux.m[pattern].explicit { panic("http: multiple registrations for " + pattern) } mux.m[pattern] = muxEntry{explicit: true, h: handler, pattern: pattern} if pattern[0] != '/' { mux.hosts = true } // Helpful behavior: // If pattern is /tree/, insert an implicit permanent redirect for /tree. // It can be overridden by an explicit registration. n := len(pattern) if n > 0 && pattern[n-1] == '/' && !mux.m[pattern[0:n-1]].explicit { // If pattern contains a host name, strip it and use remaining // path for redirect. path := pattern if pattern[0] != '/' { // In pattern, at least the last character is a '/', so // strings.Index can't be -1. path = pattern[strings.Index(pattern, "/"):] } url := &url.URL{Path: path} mux.m[pattern[0:n-1]] = muxEntry{h: RedirectHandler(url.String(), StatusMovedPermanently), pattern: pattern} }}
其實簡要之,就是構建一個pattern和函數Handler的map。看來原生庫中實現了路由非常簡單,就是一張map,所以實際應用中局限性比較大。實際應用中,我們往往利用其它路由實現,有必要也可能自己實現。