乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

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

       菌心說(shuō) 2022-02-13

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

      如下代碼為例

      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. 路由注冊(cè)

      http.HandleFunc('/byte', sayByte)

      1.1 此行代碼會(huì)調(diào)用系統(tǒng)默認(rèn)的ServeMux即DefaultServeMux,DefaultServeMux是http庫(kù)定義的一個(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中注冊(cè)路由和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ù)開(kāi)啟

      http.ListenAndServe(':8080', nil)

      2.1 監(jiān)聽(tīng)端口

      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 開(kāi)始服務(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,如果沒(méi)有用戶自己沒(méi)有初始化一個(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的初始化過(guò)程

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

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

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(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)論公約

        類似文章 更多