编辑
2024-04-09
还没写好
00
请注意,本文编写于 567 天前,最后修改于 567 天前,其中某些信息可能已经过时。

在Golang中,可以通过Context对协程做同步,或者传递上下文变量给其他协程。这样可以避免在协程之间传递大量的变量,代码更整洁可维护。下面的例子通过WithValue传递给协程一个变量,并且通过channel在协程之间通信。

  1. 支持并发读写;

  2. 写入只往当前 context 写入,不写入到父 context 中;

  3. 读取允许级联读取,当前 context 读取不到继续往父 context 读取;

  4. sync.Map

  5. 支持泛型

  6. LoadAll 返回的应该是一个新的 slice

go
package main import ( "context" "fmt" "sync" ) func worker(cancelCtx context.Context, ch chan int, wg *sync.WaitGroup) { defer wg.Done() fmt.Println(fmt.Sprintf("context value: %v", cancelCtx.Value("key1"))) for { select { case val := <-ch: fmt.Println(fmt.Sprintf("read from ch value: %d", val)) case <-cancelCtx.Done(): fmt.Println("worker is cancelled") return } } } func main() { rootCtx := context.Background() childCtx := context.WithValue(rootCtx, "key1", "value1") cancelCtx, cancelFunc := context.WithCancel(childCtx) ch := make(chan int) wg := &sync.WaitGroup{} wg.Add(1) go worker(cancelCtx, ch, wg) for i := 0; i < 10; i++ { ch <- i } cancelFunc() wg.Wait() close(ch) }

输出:

context value: value1 read from ch value: 0 read from ch value: 1 read from ch value: 2 read from ch value: 3 read from ch value: 4 read from ch value: 5 read from ch value: 6 read from ch value: 7 read from ch value: 8 read from ch value: 9 worker is cancelled

在实际的生产环境中,比如web服务器http请求处理器中,可以通过WithValue传递通用的字段给请求处理协程,比如用于多个请求之间的链路追踪:

go
package main import ( "context" "fmt" "net/http" "github.com/google/uuid" ) func welcome(w http.ResponseWriter, r *http.Request) { traceid := "" if m := r.Context().Value("traceid"); m != nil { if value, ok := m.(string); ok { traceid = value } } w.Header().Add("traceid", traceid) w.Write([]byte("Welcome to China")) } func traceID(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { traceid := uuid.New().String() ctx := context.WithValue(r.Context(), "traceid", traceid) req := r.WithContext(ctx) next.ServeHTTP(w, req) }) } func main() { welcomeHandler := http.HandlerFunc(welcome) http.Handle("/welcome", traceID(welcomeHandler)) http.ListenAndServe(":9090", nil) }

本文作者:JIeJaitt

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!