先貼一段代碼服務器
package main import ( "net/http" "fmt" "log" ) func hello(w http.ResponseWriter, r *http.Request) { r.ParseForm() fmt.Printf("%+v\n", *r.URL) fmt.Fprintln(w, "Hello world") } func main() { http.HandleFunc("/", hello) err := http.ListenAndServe(":9090", nil) if err != nil { log.Fatal(err) } }
這裏監聽本地的9090端口,使用 http.HandleFunc 將URL爲「/」的請求將其轉向名爲hello的方法。這是比較常見的Golang的簡單Web的實現,可是看着會以爲很奇怪,建議先把代碼跑起來,而後咱們再來看看源碼中Handler的定義先。併發
type Handler interface { ServeHTTP(ResponseWriter, *Request) }
如代碼中所示,Handler實際上一個接口,實現了 ServeHTTP(ResponseWriter, *Request) 這個函數,就至關於實現了一個Handler。通俗講Handler就是處理輸入輸出流的函數,將Handler註冊到路由器,等同於將特定的URL跟這個函數綁定起來,當客戶端請求訪問這個URL,路由器就會使用這個函數進行操做。
可能會有童鞋會疑問,hello這個函數並非一個Handler,爲何能夠做爲Handler註冊一個URL。這是由於這裏有一個函數叫作HandleFunc,這裏就講講HandleFunc的原理吧。先把源碼列出來:函數
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) { DefaultServeMux.HandleFunc(pattern, handler) }
HandleFunc傳入一個字符串(URL)和一個func(ResponseWriter, Request),hello這個函數是符合func(ResponseWriter, Request)的要求的,而後使用DefaultServeMux進行處理,DefaultServeMux又是什麼?在server.go的源碼中能夠輕鬆找到DefaultServeMux的定義性能
type ServeMux struct { mu sync.RWMutex m map[string]muxEntry hosts bool // whether any patterns contain hostnames } .... // DefaultServeMux is the default ServeMux used by Serve. var DefaultServeMux = &defaultServeMux var defaultServeMux ServeMux
由源碼能夠知道DefaultServeMux至關於一個公共的路由,一個公有變量,URL和Handle就是註冊到這個路由上的。須要注意的是ServeMux的成員變量,有一個sync.RWMutex,瞭解過Golang併發的應該知道,這是一個讀寫鎖(Mutiple read,single write lock, 多讀單寫鎖,容許多個讀操做並行執行,但寫操做會徹底互斥,在讀取操做比較頻繁時比sync.Mutex有着更好的性能表現),這應該也是考慮到做爲Web服務器,讀取操做會比較頻繁。接下來看mux.Handle(pattern, HandlerFunc(handler))去到哪一步,應該看到這裏有一個函數HandlerFunc(handler):code
type HandlerFunc func(ResponseWriter, *Request) // ServeHTTP calls f(w, r). func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { f(w, r) }
看到這裏你就應該明白,爲何hello這個函數沒有實現Handler方法也是一個Handler,由於HandlerFunc把hello強制實現ServeHTTP(w ResponseWriter, r *Request),因此hello這個函數也就是一個Handler。orm
這裏是路由的最後一步了server
type muxEntry struct { h Handler pattern string } // 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") } if handler == nil { panic("http: nil handler") } if _, exist := mux.m[pattern]; exist { panic("http: multiple registrations for " + pattern) } if mux.m == nil { mux.m = make(map[string]muxEntry) } mux.m[pattern] = muxEntry{h: handler, pattern: pattern} if pattern[0] != '/' { mux.hosts = true } }
公有變量DefaultServeMux將Handler註冊,這裏就用到了讀寫鎖以及一個私有結構muxEntry,到這裏,路由註冊就結束了。接口