The context.WithCancel decorator function gets a context and returns another context and a function called cancel. The returned context will be a copy of the context that has a different done channel (the channel that marks that the current context is done) that gets closed when the parent context does or when the cancel function is called – whatever happens first.
In the following example, we can see that we wait a few seconds before calling the cancel function, and the program terminates correctly. The value of Err is the context.Canceled variable:
func main() {
ctx, cancel := context.WithCancel(context.Background())
time.AfterFunc(time.Second*5, cancel)
done := ctx.Done()
for i := 0; ; i++ {
select {
case <-done:
fmt.Println("exit", ctx.Err())
return
case <-time.After(time.Second):
fmt.Println("tick", i)
}
}
}
The full example is available here: https://play.golang.org/p/fNHLIZL8e0L.