Golang Context() 的应用

在构建 HTTP 服务的时候,每一个请求都会开启一个 go 协程,然后解析处理这个请求,返回响应给客户端,这是一个请求的生命周期,有一些数据是贯穿整个生命周期的,比如 session 数据, 数据库连接。

那么如何维护这些数据,这里就用到了 Context, 以 session 为例:

package main

import (
    "context"
    "fmt"
    "github.com/gorilla/mux"
    "log"
    "net/http"
)

func SetSession(ctx context.Context, r *http.Request) context.Context {
    // ... parse cookie & get unique id , set cache
    return context.WithValue(ctx, "session", "aa123")
}

func GetSession(ctx context.Context) string {
    return ctx.Value("session").(string)
}

func SessionMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        ctx := SetSession(r.Context(), r)
        next.ServeHTTP(w, r.WithContext(ctx))
    })
}

func HomeHandler(w http.ResponseWriter, r *http.Request) {
    value := GetSession(r.Context())
    fmt.Printf("data: %s", value)
    w.Write([]byte("hello"))
}

func main() {

    route := mux.NewRouter()
    route.HandleFunc("/", HomeHandler)
    route.Use(SessionMiddleware)

    log.Fatal(http.ListenAndServe(":8080", route))
}

http 的每个请求都有 Context,通过 WithContext 设置键值,值可以是任意类型, ctx.Value 从 Context 获取指定的值, 我们构建一个 middleware 解析 cookie ,开启 session, 在 handler 中就能获取 session。