There are two different approaches to clean up a goroutine.
Use a kill channel to signal cancellation and a done channel to indicate that goroutine has been terminated.
type Worker struct {
Done chan struct{}
Kill chan struct{}
Jobs chan Job
}
func (w *Worker) Run() {
defer func() {
w.Done <- struct{}{}
}
for {
select {
case <-w.Kill:
return
case j := <-w.Jobs:
// Do some work
}
}
go w.Run()
w.Kill <- struct{}{}
Use context
to cancel
type Worker struct {
Ctx context.Context
Cancel context.CancelFunc
Jobs chan Job
}
func (w *Worker) Run() {
for {
select {
case <-w.Ctx.Done():
return
case j := <-w.Jobs:
// Do some work
}
}
go w.Run()
w.Cancel()
What are the pros/cons of each approach? Which one should I default to?
I understand that if I want to kill a tree of interconnected goroutines, I should go with context approach but let's just say I have a simple worker that doesn't start other goroutines internally.
Go 1.7 moves the golang.org/x/net/context package into the standard library as context. This allows the use of contexts for cancelation, timeouts, and passing request-scoped data in other standard library packages, including net, net/http, and os/exec, as noted below.
For more information about contexts, see the package documentation and the Go blog post “Go Concurrent Patterns: Context.”
There were problems. The context package was introduced to solve them.
Now that you have read all of the relevant documentation, What is your question?