Graceful shutdown in Go
A done channel, closed once, tells every worker to stop.
func workUntilDone(jobs <-chan int, done <-chan struct{}) []int {
var (
mu sync.Mutex
handled []int
wg sync.WaitGroup
)
for range 3 {
wg.Go(func() {
for {
select {
case job, ok := <-jobs:
if !ok {
return
}
mu.Lock()
handled = append(handled, job)
mu.Unlock()
case <-done:
return
}
}
})
}
wg.Wait()
return handled
}
How it works
- Closing a channel broadcasts: every receiver wakes.
- Workers select on their work and on done.
- Wait for them before returning, or you leak goroutines.
Keywords and builtins used here
appendcasechanforfuncifintrangereturnselectstructvar
The run, in numbers
- Lines
- 28
- Characters to type
- 326
- Tokens
- 100
- Three-star pace
- 110 tpm
At the three-star pace of 110 tokens a minute, this run takes about 55 seconds.
Step 5 of 5 in Patterns, step 23 of 25 in Concurrency.