In Golang, you can synchronize coroutines with the Context, or pass Context variables to other coroutines. This avoids passing a large number of variables between coroutines and makes the code cleaner and maintainable. The following example passes a variable to a coroutine via WithValue and communicates between coroutines via channel.

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)

}

Copy the code

Output:

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
Copy the code

In a real production environment, such as a web server HTTP request handler, a generic field can be passed WithValue to a request processing coroutine, such as link tracing between multiple requests:

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) }Copy the code