透過範例學習 Go:架構

在前一個範例中,我們研究了設定一個簡單的 HTTP 伺服器。HTTP 伺服器用來展示如何使用 `context.Context` 控制中斷。`Context` 會傳遞截止時間、中斷訊號以及其他請求範圍值,這些值會跨越 API 界線和 goroutine。

package main
import (
    "fmt"
    "net/http"
    "time"
)
func hello(w http.ResponseWriter, req *http.Request) {

`net/http` 機制會針對每個請求建立一個 `context.Context`,並透過 `Context()` 方法提供。

    ctx := req.Context()
    fmt.Println("server: hello handler started")
    defer fmt.Println("server: hello handler ended")

在傳送回應給客戶端之前,等待幾秒鐘。這可以模擬伺服器正在執行的一些工作。在工作的過程中,請持續監控架構的 `Done()` 管道,取得一個訊號,表示我們應該取消工作,並盡快傳回。

    select {
    case <-time.After(10 * time.Second):
        fmt.Fprintf(w, "hello\n")
    case <-ctx.Done():

架構的 `Err()` 方法會傳回一個錯誤,說明 `Done()` 管道為何會關閉。

        err := ctx.Err()
        fmt.Println("server:", err)
        internalError := http.StatusInternalServerError
        http.Error(w, err.Error(), internalError)
    }
}
func main() {

和前面一樣,我們在「/hello」路徑上註冊我們的處理常式,然後開始提供服務。

    http.HandleFunc("/hello", hello)
    http.ListenAndServe(":8090", nil)
}

在背景中執行伺服器。

$ go run context-in-http-servers.go &

模擬一個對 `/hello` 的客戶端請求,在開始後不久按下 Ctrl+C 以發出中斷訊號。

$ curl localhost:8090/hello
server: hello handler started
^C
server: context canceled
server: hello handler ended

下一個範例:產生程序