- ListenAndServe執(zhí)行流程如下圖局蚀,Go為了實現(xiàn)高并發(fā)和高性能, 使用了goroutines來處理Conn的讀寫事件, 這樣每個請求都能保持獨立,相互不會阻塞恕稠,可以高效的響應(yīng)網(wǎng)絡(luò)事件琅绅。這是Go高效的保證。
一鹅巍、ListenAndServe流程圖
3.3.illustrator.png
二千扶、GoWeb詳細執(zhí)行流程
- 首先調(diào)用
http.HandleFunc
,按順序做了幾件事:
- 調(diào)用了DefaultServeMux的HandleFunc
- 調(diào)用了DefaultServeMux的Handle
- 往DefaultServeMux的map[string]muxEntry中增加對應(yīng)的handler和路由規(guī)則
- 其次調(diào)用
http.ListenAndServe(":9090", nil)
骆捧,按順序做了幾件事情:
- 實例化Server
- 調(diào)用Server的ListenAndServe()
- 調(diào)用
net.Listen("tcp", addr)
監(jiān)聽端口 - 啟動一個for循環(huán)澎羞,在循環(huán)體中Accept請求
- 對每個請求實例化一個Conn,并且開啟一個goroutine為這個請求進行服務(wù)
go c.serve()
- 在中讀取每個請求的內(nèi)容
w, err := c.readRequest()
- 判斷handler是否為空敛苇,如果沒有設(shè)置handler(這個例子就沒有設(shè)置handler)妆绞,handler就設(shè)置為DefaultServeMux
- 調(diào)用handler的ServeHttp
- 在這個例子中,下面就進入到DefaultServeMux.ServeHttp
- 根據(jù)request選擇handler,并且進入到這個handler的ServeHTTP
mux.handler(r).ServeHTTP(w, r)
- 選擇handler:
A 判斷是否有路由能滿足這個request(循環(huán)遍歷ServerMux的muxEntry)
B 如果有路由滿足括饶,調(diào)用這個路由handler的ServeHttp
C 如果沒有路由滿足株茶,調(diào)用NotFoundHandler的ServeHttp