使用 Golang 打造 Web 應用程式
  • Introduction
  • Go 環境配置
    • Go 安裝
    • GOPATH 與工作空間
    • Go 命令
    • Go 開發工具
    • 小結
  • Go 語言基礎
    • 你好,Go
    • Go 基礎
    • 流程和函式
    • struct
    • 物件導向
    • interface
    • 併發
    • 小結
  • Web 基礎
    • web 工作方式
    • Go 建立一個簡單的 web 服務
    • Go 如何使得 web 工作
    • Go 的 http 套件詳解
    • 小結
  • 表單
    • 處理表單的輸入
    • 驗證表單的輸入
    • 預防跨站指令碼
    • 防止多次提交表單
    • 處理檔案上傳
    • 小結
  • 存取資料庫
    • database/sql 介面
    • 使用 MySQL 資料庫
    • 使用 SQLite 資料庫
    • 使用 PostgreSQL 資料庫
    • 使用 beedb 函式庫進行 ORM 開發
    • NoSQL 資料庫操作
    • 小結
  • session 和資料儲存
    • session 和 cookie
    • Go 如何使用 session
    • session 儲存
    • 預防 session 劫持
    • 小結
  • 文字檔案處理
    • XML 處理
    • JSON 處理
    • 正則處理
    • 範本處理
    • 檔案操作
    • 字串處理
    • 小結
  • Web 服務
    • Socket 程式設計
    • WebSocket
    • REST
    • RPC
    • 小結
  • 安全與加密
    • 預防 CSRF 攻擊
    • 確保輸入過濾
    • 避免 XSS 攻擊
    • 避免 SQL 注入
    • 儲存密碼
    • 加密和解密資料
    • 小結
  • 國際化和本地化
    • 設定預設地區
    • 本地化資源
    • 國際化站點
    • 小結
  • 錯誤處理,除錯和測試
    • 錯誤處理
    • 使用 GDB 除錯
    • Go 怎麼寫測試案例
    • 小結
  • 部署與維護
    • 應用日誌
    • 網站錯誤處理
    • 應用部署
    • 備份和還原
    • 小結
  • 如何設計一個 Web 框架
    • 專案規劃
    • 自訂路由器設計
    • controller 設計
    • 日誌和配置設計
    • 實現部落格的增刪改
    • 小結
  • 擴充套件 Web 框架
    • 靜態檔案支援
    • Session 支援
    • 表單支援
    • 使用者認證
    • 多語言支援
    • pprof 支援
    • 小結
  • 參考資料
Powered by GitBook
On this page
  • web 工作方式的幾個概念
  • 分析 http 套件執行機制
  • links

Was this helpful?

  1. Web 基礎

Go 如何使得 web 工作

PreviousGo 建立一個簡單的 web 服務NextGo 的 http 套件詳解

Last updated 4 years ago

Was this helpful?

前面小節介紹了如何透過 Go 建立一個 Web 服務,我們可以看到簡單應用一個 net/http 套件就方便的建立起來了。那麼 Go 在底層到底是怎麼做的呢?萬變不離其宗,Go 的 Web 服務工作也離不開我們第一小節介紹的 Web 工作方式。

web 工作方式的幾個概念

以下均是伺服器端的幾個概念

Request:使用者請求的資訊,用來解析使用者的請求資訊,包括 post、get、cookie、url 等資訊

Response:伺服器需要反饋給客戶端的資訊

Conn:使用者的每次請求連結

Handler:處理請求和產生回傳資訊的處理邏輯

分析 http 套件執行機制

下圖是 Go 實現 Web 服務的工作模式的流程圖

圖 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 的資訊反饋到客戶端。

詳細的整個流程如下圖所示:

圖 3.10 一個 http 連線處理流程

至此我們的三個問題已經全部得到了解答,你現在對於 Go 如何讓 Web 跑起來的是否已經基本了解了呢?

links

上一節:

下一節:

目錄
GO 建立一個簡單的 web 服務
Go 的 http 套件詳解