先贴一段代码服务器
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,到这里,路由注册就结束了。接口