<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                前面小節介紹了如何通過Go搭建一個Web服務,我們可以看到簡單應用一個net/http包就方便的搭建起來了。那么Go在底層到底是怎么做的呢?萬變不離其宗,Go的Web服務工作也離不開我們第一小節介紹的Web工作方式。 ## [](https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/03.3.md#web工作方式的幾個概念)web工作方式的幾個概念 以下均是服務器端的幾個概念 Request:用戶請求的信息,用來解析用戶的請求信息,包括post、get、cookie、url等信息 Response:服務器需要反饋給客戶端的信息 Conn:用戶的每次請求鏈接 Handler:處理請求和生成返回信息的處理邏輯 ## [](https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/03.3.md#分析http包運行機制)分析http包運行機制 如下圖所示,是Go實現Web服務的工作模式的流程圖 [![](https://github.com/astaxie/build-web-application-with-golang/raw/master/zh/images/3.3.http.png?raw=true)](https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/images/3.3.http.png?raw=true) 圖3.9 http包執行流程 1. 創建Listen Socket, 監聽指定的端口, 等待客戶端請求到來。 2. Listen Socket接受客戶端的請求, 得到Client Socket, 接下來通過Client Socket與客戶端通信。 3. 處理客戶端的請求, 首先從Client Socket讀取HTTP請求的協議頭, 如果是POST方法, 還可能要讀取客戶端提交的數據, 然后交給相應的handler處理請求, handler處理完畢準備好客戶端需要的數據, 通過Client Socket寫給客戶端。 這整個的過程里面我們只要了解清楚下面三個問題,也就知道Go是如何讓Web運行起來了 * 如何監聽端口? * 如何接收客戶端請求? * 如何分配handler? 前面小節的代碼里面我們可以看到,Go是通過一個函數`ListenAndServe`來處理這些事情的,這個底層其實這樣處理的:初始化一個server對象,然后調用了`net.Listen("tcp", addr)`,也就是底層用TCP協議搭建了一個服務,然后監控我們設置的端口。 下面代碼來自Go的http包的源碼,通過下面的代碼我們可以看到整個的http處理過程: ~~~ 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() } } ~~~ 監控之后如何接收客戶端的請求呢?上面代碼執行監控端口之后,調用了`srv.Serve(net.Listener)`函數,這個函數就是處理接收客戶端的請求信息。這個函數里面起了一個`for{}`,首先通過Listener接收請求,其次創建一個Conn,最后單獨開了一個goroutine,把這個請求的數據當做參數扔給這個conn去服務:`go c.serve()`。這個就是高并發體現了,用戶的每一次請求都是在一個新的goroutine去服務,相互不影響。 那么如何具體分配到相應的函數來處理請求呢?conn首先會解析request:`c.readRequest()`,然后獲取相應的handler:`handler := c.server.Handler`,也就是我們剛才在調用函數`ListenAndServe`時候的第二個參數,我們前面例子傳遞的是nil,也就是為空,那么默認獲取`handler = DefaultServeMux`,那么這個變量用來做什么的呢?對,這個變量就是一個路由器,它用來匹配url跳轉到其相應的handle函數,那么這個我們有設置過嗎?有,我們調用的代碼里面第一句不是調用了`http.HandleFunc("/", sayhelloName)`嘛。這個作用就是注冊了請求`/`的路由規則,當請求uri為"/",路由就會轉到函數sayhelloName,DefaultServeMux會調用ServeHTTP方法,這個方法內部其實就是調用sayhelloName本身,最后通過寫入response的信息反饋到客戶端。 詳細的整個流程如下圖所示: [![](https://github.com/astaxie/build-web-application-with-golang/raw/master/zh/images/3.3.illustrator.png?raw=true)](https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/images/3.3.illustrator.png?raw=true) 圖3.10 一個http連接處理流程 至此我們的三個問題已經全部得到了解答,你現在對于Go如何讓Web跑起來的是否已經基本了解呢?
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看