有人曾和我說過,一門語言應該可以本身實現一個HTTP服務。PHP作不到,但GO卻垂手可得。
只須要幾行代碼,GO就能夠實現一個簡單的HTTP服務。nginx
package main import ( "fmt" "net/http" ) func IndexHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "hello world") } func main() { http.HandleFunc("/", IndexHandler) http.ListenAndServe(":8001", nil) }
這樣,便可監聽8001端口,而且當有請求訪問的時候完成響應。(這幾乎就完成了nginx的主要功能,不過沒有作負載平衡)
觀察這段代碼,咱們基本可以從命名大概瞭解每一個函數的做用。服務器
http.HandleFunc("/", IndexHandler)
這至關於綁定url的函數,當請求的url是"/"時,那麼將這個請求交給IndexHandler來處理。cookie
http.ListenAndServe(":8001", nil)
顧名思義,監聽8001端口而且啓動服務。併發
func IndexHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "hello world") }
處理函數,當有請求的時候輸出hello world。
經過以上分析,GO搭建一個HTTP服務只需用到一個net/http包便可。同時結合上篇文章,要完成http服務須要如下幾點tcp
前3點是一個HTTP服務必需要的結構,第4點是每個HTTP服務的核心所在。
咱們只須要了解3個問題,就知道GO是如何將Web服務運做起來。函數
GO是經過一個函數 ListenAndServe
作到的。
首先初始化一個server對象,而後調用net.Listen("tcp", addr)
底層創建TCP鏈接,監聽咱們設置的端口。高併發
這塊的源碼post
func (srv *Server) Serve(l net.Listener) error { defer l.Close() var tempDelay time.Duration // how long to sleep on accept failure for { rw, e := l.Accept() if e != nil { if ne, ok := e.(net.Error); ok && ne.Temporary() { if tempDelay == 0 { tempDelay = 5 * time.Millisecond } else { tempDelay *= 2 } if max := 1 * time.Second; tempDelay > max { tempDelay = max } log.Printf("http: Accept error: %v; retrying in %v", e, tempDelay) time.Sleep(tempDelay) continue } return e } tempDelay = 0 c, err := srv.newConn(rw) if err != nil { continue } go c.serve() } }
這段代碼首先起了一個for()
。接收請求Accept()
,如有請求,則創建一個Conn鏈接,並用協程啓動服務。這時再次進入下一個循環,如有請求則新創建一個鏈接並啓動一個協程服務。若沒有請求,則休息一段時間後再次循環。正是利用了go協程特性,用戶的每個請求都有一個新的goroutine去服務,互不影響,達到了自然支持高併發特性。url
在創建conn以後,conn會首先解析request,c.readRequest()
,而後得到相應的handle:handler := c.server.Handler
,也就是咱們剛纔在調用函數ListenAndServe
時候的第二個參數,咱們前面例子傳遞的是nil,也就是爲空,那麼默認獲取handler = DefaultServeMux
,那麼這個變量用來作什麼的呢?對,這個變量就是一個路由器,它用來匹配url跳轉到其相應的handle函數,那麼這個咱們有設置過嗎?有,咱們調用的代碼裏面第一句不是調用了http.HandleFunc("/", IndexHandler)
嘛。這個做用就是註冊了請求/的路由規則,當請求uri爲"/",路由就會轉到函數IndexHandler
,DefaultServeMux
會調用ServeHTTP
方法,這個方法內部其實就是調用IndexHandler
自己,最後經過寫入response
的信息反饋到客戶端。code