建議看這篇文章前先看一下net/http文檔 http://golang.org/pkg/net/http/html
net.http包裏面有不少文件,都是和http協議相關的,好比設置cookie,header等。其中最重要的一個文件就是server.go了,這裏咱們閱讀的就是這個文件。golang
ResponseWriter: 生成Response的接口緩存
Handler: 處理請求和生成返回的接口cookie
ServeMux: 路由,後面會說到ServeMux也是一種Handler網絡
Conn : 網絡鏈接併發
實現了handler接口的對象就意味着往server端添加了處理請求的邏輯。函數
type Handler interface { ServeHTTP(ResponseWriter, *Request) // 具體的邏輯函數 }
下面是三個接口(ResponseWriter, Flusher, Hijacker):google
// ResponseWriter的做用是被Handler調用來組裝返回的Response的 type ResponseWriter interface { // 這個方法返回Response返回的Header供讀寫 Header() Header // 這個方法寫Response的Body Write([]byte) (int, error) // 這個方法根據HTTP State Code來寫Response的Header WriteHeader(int) } // Flusher的做用是被Handler調用來將寫緩存中的數據推給客戶端 type Flusher interface { // 這個方法將寫緩存中數據推送給客戶端 Flush() } // Hijacker的做用是被Handler調用來關閉鏈接的 type Hijacker interface { // 這個方法讓調用者主動管理鏈接 Hijack() (net.Conn, *bufio.ReadWriter, error) }
實現這三個接口的結構是response(這個結構是http包私有的,在文檔中並無顯示,須要去看源碼)spa
// response包含了全部server端的http返回信息 type response struct { conn *conn // 保存這次HTTP鏈接的信息 req *Request // 對應請求信息 chunking bool // 是否使用chunk wroteHeader bool // header是否已經執行過寫操做 wroteContinue bool // 100 Continue response was written header Header // 返回的http的Header written int64 // Body的字節數 contentLength int64 // Content長度 status int // HTTP狀態 needSniff bool // 是否須要使用sniff。(當沒有設置Content-Type的時候,開啓sniff能根據HTTP body來肯定Content-Type) closeAfterReply bool //是否保持長連接。若是客戶端發送的請求中connection有keep-alive,這個字段就設置爲false。 requestBodyLimitHit bool //是否requestBody太大了(當requestBody太大的時候,response是會返回411狀態的,並把鏈接關閉) }
在response中是能夠看到設計
func (w *response) Header() Header func (w *response) WriteHeader(code int) func (w *response) Write(data []byte) (n int, err error) func (w *response) Flush() func (w *response) Hijack() (rwc net.Conn, buf *bufio.ReadWriter, err error)
這麼幾個方法。因此說response實現了ResponseWriter,Flusher,Hijacker這三個接口
handlerFunc是常常使用到的一個type
type HandlerFunc func(ResponseWriter, *Request) // ServeHTTP calls f(w, r). func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { f(w, r) }
這裏須要多回味一下了,這個HandlerFunc定義和ServeHTTP合起來是說明了什麼?說明HandlerFunc的全部實例是實現了ServeHttp方法的。另,實現了ServeHttp方法就是什麼?實現了接口Handler!
因此你之後會看到不少這樣的句子:
func AdminHandler(w ResponseWriter, r *Request) { ... } handler := HandlerFunc(AdminHandler) handler.ServeHttp(w,r)
請不要訝異,你明明沒有寫ServeHttp,怎麼能調用呢? 實際上調用ServeHttp就是調用AdminHandler。
HandlerFunc(AdminHandler)是一個轉換而非一個函數調用,由於http.HandlerFunc是一個類型。HandlerFunc顯示了在Go語言接口機制中一些不一樣尋常的特色。這是一個有實現了接口http.Handler方法的函數類型。ServeHTTP方法的行爲調用了它自己的函數。所以HandlerFunc是一個讓函數值知足一個接口的適配器(此處是http.Handler接口適配器,由於serverHTTP實現了Handler接口),這裏函數和這個接口僅有的方法有相同的函數簽名。實際上,這個技巧讓一個單一的類型例如MyHandler以多種方式知足http.Handler接口。
附帶上一個play.google寫的一個小例子
http://play.golang.org/p/nSt_wcjc2u
有興趣繼續研究的同窗能夠繼續試驗下去
下面接着看Server.go
它就是http包中的路由規則器。你能夠在ServerMux中註冊你的路由規則,當有請求到來的時候,根據這些路由規則來判斷將請求分發到哪一個處理器(Handler)。
它的結構以下:
type ServeMux struct { mu sync.RWMutex //鎖,因爲請求設計到併發處理,所以這裏須要一個鎖機制 m map[string]muxEntry // 路由規則,一個string對應一個mux實體,這裏的string就是我註冊的路由表達式 }
下面看一下muxEntry
type muxEntry struct { explicit bool // 是否精確匹配 h Handler // 這個路由表達式對應哪一個handler }
看到這兩個結構就應該對請求是如何路由的有思路了:
ServeMux定義的方法有:
func (mux *ServeMux) match(path string) Handler //根據path獲取Handler func (mux *ServeMux) handler(r *Request) Handler //根據Request獲取Handler,內部實現調用match func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) //!!這個說明,ServeHttp也實現了Handler接口,它實際上也是一個Handler!內部實現調用handler func (mux *ServeMux) Handle(pattern string, handler Handler) //註冊handler方法 func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) //註冊handler方法(直接使用func註冊)
在godoc文檔中常常見到的DefaultServeMux是http默認使用的ServeMux
var DefaultServeMux = NewServeMux()
若是咱們沒有自定義ServeMux,系統默認使用這個ServeMux。
換句話說,http包外層(非ServeMux)中提供的幾個方法:
func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) } func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) { DefaultServeMux.HandleFunc(pattern, handler) }
實際上就是調用ServeMux結構內部對應的方法。
下面還剩下一個Server結構
type Server struct { Addr string // 監聽的地址和端口 Handler Handler // 全部請求須要調用的Handler(實際上這裏說是ServeMux更確切)若是爲空則設置爲DefaultServeMux ReadTimeout time.Duration // 讀的最大Timeout時間 WriteTimeout time.Duration // 寫的最大Timeout時間 MaxHeaderBytes int // 請求頭的最大長度 TLSConfig *tls.Config // 配置TLS }
Server提供的方法有:
func (srv *Server) Serve(l net.Listener) error //對某個端口進行監聽,裏面就是調用for進行accept的處理了 func (srv *Server) ListenAndServe() error //開啓http server服務,內部調用Serve func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error //開啓https server服務,內部調用Serve
固然Http包也直接提供了方法供外部使用,實際上內部就是實例化一個Server,而後調用ListenAndServe方法
func ListenAndServe(addr string, handler Handler) error //開啓Http服務 func ListenAndServeTLS(addr string, certFile string, keyFile string, handler Handler) error //開啓HTTPs服務
參考:http://www.cnblogs.com/yjf512/archive/2012/08/22/2650873.html