Concurrency and Packages
Context Worker Value
A context can carry request metadata into a goroutine without using shared global state.
context value
Pass a context into a worker goroutine and send the derived label back through a channel.
Context Worker Value
context_worker_value.go
Replay: real traced execution (multi-file project)
package main
import (
"context"
"fmt"
)
func main() {
var requestID = "A1"
ctx := context.WithValue(context.Background(), "request", requestID)
done := make(chan string, 1)
go func(workerContext context.Context) {
value := workerContext.Value("request").(string)
done <- "handled:" + value
}(ctx)
message := <-done
fmt.Println("requestID=", requestID)
fmt.Println("message=", message)
fmt.Println("done=", true)
}
package main
import (
"context"
"fmt"
)
func main() {
var requestID = "B2"
ctx := context.WithValue(context.Background(), "request", requestID)
done := make(chan string, 1)
go func(workerContext context.Context) {
value := workerContext.Value("request").(string)
done <- "handled:" + value
}(ctx)
message := <-done
fmt.Println("requestID=", requestID)
fmt.Println("message=", message)
fmt.Println("done=", true)
}
package main
import (
"context"
"fmt"
)
func main() {
var requestID = "C3"
ctx := context.WithValue(context.Background(), "request", requestID)
done := make(chan string, 1)
go func(workerContext context.Context) {
value := workerContext.Value("request").(string)
done <- "handled:" + value
}(ctx)
message := <-done
fmt.Println("requestID=", requestID)
fmt.Println("message=", message)
fmt.Println("done=", true)
}
requestID ← "A1", ctx ← &context.valueCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, key:"request", val:"A1"}
8func main() {9 var requestID→ "A1" = "A1" //@requestID="B2", "C3"10 ctx→ &context.valueCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, key:"request", val:"A1"} := context.WithValue(context.Background(), "request", requestID"A1")11 done→ (chan string)(⟨addr A⟩) := make(chan string, 1)1213 go func(workerContext context.Context) {14 value := workerContext.Value("request").(string)15 done <- "handled:" + value16 }(ctx&context.valueCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, key:"request", val:"A1"})1718 message := <-done(chan string)(⟨addr A⟩)value ← "A1"
13go func(workerContext&context.valueCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, key:"request", val:"A1"} context.Context) {14 value→ "A1" := workerContext.Value("request").(string)15 done(chan string)(⟨addr A⟩) <- "handled:" + value"A1"16}(ctx)message ← "handled:A1"
18 message→ "handled:A1" := <-done(chan string)(⟨addr A⟩)1920 fmt.Println("requestID=", requestID"A1")21 fmt.Println("message=", message"handled:A1")22 fmt.Println("done=", true)23}outputrequestID= A1 message= handled:A1 done= true
requestID ← "B2", ctx ← &context.valueCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, key:"request", val:"B2"}
8func main() {9 var requestID→ "B2" = "B2"10 ctx→ &context.valueCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, key:"request", val:"B2"} := context.WithValue(context.Background(), "request", requestID"B2")11 done→ (chan string)(⟨addr A⟩) := make(chan string, 1)1213 go func(workerContext context.Context) {14 value := workerContext.Value("request").(string)15 done <- "handled:" + value16 }(ctx&context.valueCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, key:"request", val:"B2"})1718 message := <-done(chan string)(⟨addr A⟩)value ← "B2"
13go func(workerContext&context.valueCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, key:"request", val:"B2"} context.Context) {14 value→ "B2" := workerContext.Value("request").(string)15 done(chan string)(⟨addr A⟩) <- "handled:" + value"B2"16}(ctx)message ← "handled:B2"
18 message→ "handled:B2" := <-done(chan string)(⟨addr A⟩)1920 fmt.Println("requestID=", requestID"B2")21 fmt.Println("message=", message"handled:B2")22 fmt.Println("done=", true)23}outputrequestID= B2 message= handled:B2 done= true
requestID ← "C3", ctx ← &context.valueCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, key:"request", val:"C3"}
8func main() {9 var requestID→ "C3" = "C3"10 ctx→ &context.valueCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, key:"request", val:"C3"} := context.WithValue(context.Background(), "request", requestID"C3")11 done→ (chan string)(⟨addr A⟩) := make(chan string, 1)1213 go func(workerContext context.Context) {14 value := workerContext.Value("request").(string)15 done <- "handled:" + value16 }(ctx&context.valueCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, key:"request", val:"C3"})1718 message := <-done(chan string)(⟨addr A⟩)value ← "C3"
13go func(workerContext&context.valueCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, key:"request", val:"C3"} context.Context) {14 value→ "C3" := workerContext.Value("request").(string)15 done(chan string)(⟨addr A⟩) <- "handled:" + value"C3"16}(ctx)message ← "handled:C3"
18 message→ "handled:C3" := <-done(chan string)(⟨addr A⟩)1920 fmt.Println("requestID=", requestID"C3")21 fmt.Println("message=", message"handled:C3")22 fmt.Println("done=", true)23}outputrequestID= C3 message= handled:C3 done= true