Context and Cancellation
Cancel Signal
A cancel function marks a context as done without stopping the program immediately.
cancel function
`context.WithCancel` returns a child context and a function that records cancellation.
Cancel Signal
cancel_signal.go
Replay: real traced execution (multi-file project)
package main
import (
"context"
"fmt"
)
func main() {
var task = "sync"
ctx, cancel := context.WithCancel(context.Background())
fmt.Println("task=", task)
fmt.Println("beforeCancel=", ctx.Err() == nil)
cancel()
fmt.Println("afterCancel=", ctx.Err())
}
package main
import (
"context"
"fmt"
)
func main() {
var task = "build"
ctx, cancel := context.WithCancel(context.Background())
fmt.Println("task=", task)
fmt.Println("beforeCancel=", ctx.Err() == nil)
cancel()
fmt.Println("afterCancel=", ctx.Err())
}
package main
import (
"context"
"fmt"
)
func main() {
var task = "review"
ctx, cancel := context.WithCancel(context.Background())
fmt.Println("task=", task)
fmt.Println("beforeCancel=", ctx.Err() == nil)
cancel()
fmt.Println("afterCancel=", ctx.Err())
}
task ← "sync", ctx ← &context.cancelCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, mu:sync.Mutex{state:0, sema:0x0}, done:atomic.Value{v:interface {}(nil)}, children:map[context.canceler]struct {}(nil), err:error(nil), cause:error(nil)}
8func main() {9 var task→ "sync" = "sync" //@task="build", "review"10 ctx→ &context.cancelCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, mu:sync.Mutex{state:0, sema:0x0}, done:atomic.Value{v:interface {}(nil)}, children:map[context.canceler]struct {}(nil), err:error(nil), cause:error(nil)}, cancel→ (context.CancelFunc)(⟨addr A⟩) := context.WithCancel(context.Background())1112 fmt.Println("task=", task"sync")13 fmt.Println("beforeCancel=", ctx&context.cancelCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, mu:sync.Mutex{state:0, sema:0x0}, done:atomic.Value{v:interface {}(nil)}, children:map[context.canceler]struct {}(nil), err:error(nil), cause:error(nil)}.Err() == nil)1415 cancel()16 fmt.Println("afterCancel=", ctx&context.cancelCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, mu:sync.Mutex{state:0, sema:0x0}, done:atomic.Value{v:(chan struct {})(⟨addr B⟩)}, children:map[context.canceler]struct {}(nil), err:(*errors.errorString)(⟨addr C⟩), cause:(*errors.errorString)(⟨addr C⟩)}.Err())17}outputtask= sync beforeCancel= true afterCancel= context canceled
task ← "build", ctx ← &context.cancelCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, mu:sync.Mutex{state:0, sema:0x0}, done:atomic.Value{v:interface {}(nil)}, children:map[context.canceler]struct {}(nil), err:error(nil), cause:error(nil)}
8func main() {9 var task→ "build" = "build"10 ctx→ &context.cancelCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, mu:sync.Mutex{state:0, sema:0x0}, done:atomic.Value{v:interface {}(nil)}, children:map[context.canceler]struct {}(nil), err:error(nil), cause:error(nil)}, cancel→ (context.CancelFunc)(⟨addr A⟩) := context.WithCancel(context.Background())1112 fmt.Println("task=", task"build")13 fmt.Println("beforeCancel=", ctx&context.cancelCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, mu:sync.Mutex{state:0, sema:0x0}, done:atomic.Value{v:interface {}(nil)}, children:map[context.canceler]struct {}(nil), err:error(nil), cause:error(nil)}.Err() == nil)1415 cancel()16 fmt.Println("afterCancel=", ctx&context.cancelCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, mu:sync.Mutex{state:0, sema:0x0}, done:atomic.Value{v:(chan struct {})(⟨addr B⟩)}, children:map[context.canceler]struct {}(nil), err:(*errors.errorString)(⟨addr C⟩), cause:(*errors.errorString)(⟨addr C⟩)}.Err())17}outputtask= build beforeCancel= true afterCancel= context canceled
task ← "review", ctx ← &context.cancelCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, mu:sync.Mutex{state:0, sema:0x0}, done:atomic.Value{v:interface {}(nil)}, children:map[context.canceler]struct {}(nil), err:error(nil), cause:error(nil)}
8func main() {9 var task→ "review" = "review"10 ctx→ &context.cancelCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, mu:sync.Mutex{state:0, sema:0x0}, done:atomic.Value{v:interface {}(nil)}, children:map[context.canceler]struct {}(nil), err:error(nil), cause:error(nil)}, cancel→ (context.CancelFunc)(⟨addr A⟩) := context.WithCancel(context.Background())1112 fmt.Println("task=", task"review")13 fmt.Println("beforeCancel=", ctx&context.cancelCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, mu:sync.Mutex{state:0, sema:0x0}, done:atomic.Value{v:interface {}(nil)}, children:map[context.canceler]struct {}(nil), err:error(nil), cause:error(nil)}.Err() == nil)1415 cancel()16 fmt.Println("afterCancel=", ctx&context.cancelCtx{Context:context.backgroundCtx{emptyCtx:context.emptyCtx{}}, mu:sync.Mutex{state:0, sema:0x0}, done:atomic.Value{v:(chan struct {})(⟨addr B⟩)}, children:map[context.canceler]struct {}(nil), err:(*errors.errorString)(⟨addr C⟩), cause:(*errors.errorString)(⟨addr C⟩)}.Err())17}outputtask= review beforeCancel= true afterCancel= context canceled