久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

理解Go/Golang http庫的請(qǐng)求解析過程

 菌心說 2022-02-13

http是go自帶的web開發(fā)庫,,具有非常強(qiáng)大的web開發(fā)功能,。本文以一個(gè)代碼為例講解請(qǐng)求的解析過程,。

如下代碼為例

  1. func main() {
  2. http.HandleFunc('/byte', sayByte)
  3. http.ListenAndServe(':8080', nil)
  4. }
  5. func sayByte(writer http.ResponseWriter, request *http.Request) {
  6. writer.Write([]byte(' say byte byte!!'))
  7. }

1. 路由注冊

http.HandleFunc('/byte', sayByte)

1.1 此行代碼會(huì)調(diào)用系統(tǒng)默認(rèn)的ServeMux即DefaultServeMux,,DefaultServeMux是http庫定義的一個(gè)變量。

DefaultServeMux.HandleFunc(pattern, handler)  // serve.go  2380行

1.2 并且利用HandlerFunc將函數(shù)sayByte轉(zhuǎn)換成handler,,

mux.Handle(pattern, HandlerFunc(handler))  // serve.go 2368行

1.3 真正向DefaultServeMux中注冊路由和handler的是ServeMux的handle函數(shù)

  1. func (mux *ServeMux) Handle(pattern string, handler Handler) { // serve.go 2342
  2. mux.mu.Lock()
  3. defer mux.mu.Unlock()
  4. if pattern == '' {
  5. panic('http: invalid pattern')
  6. }
  7. if handler == nil {
  8. panic('http: nil handler')
  9. }
  10. if _, exist := mux.m[pattern]; exist {
  11. panic('http: multiple registrations for ' + pattern)
  12. }
  13. if mux.m == nil {
  14. mux.m = make(map[string]muxEntry)
  15. }
  16. mux.m[pattern] = muxEntry{h: handler, pattern: pattern}
  17. if pattern[0] != '/' {
  18. mux.hosts = true
  19. }
  20. }

1.4 查看ServeMux結(jié)構(gòu)可知,,路由和handler存儲(chǔ)在ServeMux的m屬性中,m是一個(gè)map

  1. type ServeMux struct { //serve.go 2133
  2. mu sync.RWMutex
  3. m map[string]muxEntry
  4. hosts bool // whether any patterns contain hostnames
  5. }

到此完成DefaultServeMux的初始化,,也就是路由與handler的一一對(duì)應(yīng)關(guān)系,,存儲(chǔ)在一個(gè)map中,鍵是路由,,值是muxEntry,,而由他存儲(chǔ)路由與handler。

2.服務(wù)開啟

http.ListenAndServe(':8080', nil)

2.1 監(jiān)聽端口

ln, err := net.Listen('tcp', addr) //serve.go 2707

2.2 接受請(qǐng)求

rw, e := l.Accept()  //serve.go 2770

2.3 為請(qǐng)求創(chuàng)建一個(gè)連接

c := srv.newConn(rw) //serve.go 2793

2.4 開始服務(wù)

go c.serve(ctx)  //serve.go 2795

2.5 初始化ServerHandler,,并且調(diào)用他的ServeHTTP方法

serverHandler{c.server}.ServeHTTP(w, w.req)  // serve.go //1830

2.6 ServeHttp方法會(huì)找出服務(wù)的一個(gè)ServeMux,,如果沒有用戶自己沒有初始化一個(gè)ServeMux,則會(huì)使用DefaultServeMux,,也就是之前默認(rèn)初始化的ServeMux,,最后調(diào)用ServeMux的serveHTTP方法。

  1. func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) { //serve.go 2686
  2. handler := sh.srv.Handler
  3. if handler == nil {
  4. handler = DefaultServeMux
  5. }
  6. if req.RequestURI == '*' && req.Method == 'OPTIONS' {
  7. handler = globalOptionsHandler{}
  8. }
  9. handler.ServeHTTP(rw, req)
  10. }

2.7 在ServeMux的serveHTTP方法中,,找到處理函數(shù)并調(diào)用

  1. func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) { //serve.go 2328
  2. if r.RequestURI == '*' {
  3. if r.ProtoAtLeast(1, 1) {
  4. w.Header().Set('Connection', 'close')
  5. }
  6. w.WriteHeader(StatusBadRequest)
  7. return
  8. }
  9. h, _ := mux.Handler(r) //根據(jù)url在ServeMux中的m屬性中找到處理函數(shù),,
  10. h.ServeHTTP(w, r) //調(diào)用處理函數(shù)
  11. }

2.8 尋找處理函數(shù)的代碼

  1. func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) { /serve.go 2309
  2. mux.mu.RLock()
  3. defer mux.mu.RUnlock()
  4. // Host-specific pattern takes precedence over generic ones
  5. if mux.hosts {
  6. h, pattern = mux.match(host + path)
  7. }
  8. if h == nil {
  9. h, pattern = mux.match(path)
  10. }
  11. if h == nil {
  12. h, pattern = NotFoundHandler(), ''
  13. }
  14. return
  15. }
  1. func (mux *ServeMux) match(path string) (h Handler, pattern string) { // serve.go 2197
  2. // Check for exact match first.
  3. v, ok := mux.m[path]
  4. if ok {
  5. return v.h, v.pattern
  6. }
  7. // Check for longest valid match.
  8. var n = 0
  9. for k, v := range mux.m {
  10. if !pathMatch(k, path) {
  11. continue
  12. }
  13. if h == nil || len(k) > n {
  14. n = len(k)
  15. h = v.h
  16. pattern = v.pattern
  17. }
  18. }
  19. return
  20. }

注意:觀察到ServeMux的m屬性的值是muxEntry,結(jié)構(gòu)如下

  1. type muxEntry struct { //serve.go 2139
  2. h Handler
  3. pattern string
  4. }

此處的handler是一個(gè)接口,,在如下代碼中,,我們傳入的是函數(shù),最終由HandlerFunc將函數(shù)轉(zhuǎn)成Handler,。

http.HandleFunc('/byte', sayByte)

我們也可以直接實(shí)現(xiàn)Handler ,那么此時(shí)代碼如下

  1. type MyHandler struct{}
  2. func (h *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  3. fmt.Fprintf(w, 'Hello World!')
  4. }
  5. func main() {
  6. handler := MyHandler{}
  7. http.Handle('/hello',&handler)
  8. http.ListenAndServe(':8080',nil)
  9. }

文章到此為止,,介紹了

1.ServeMux的初始化過程

2.web請(qǐng)求處理過程

文中如果有錯(cuò)誤還請(qǐng)嚴(yán)厲指出。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多