Skip to content

Instantly share code, notes, and snippets.

@frncmx
Last active January 31, 2019 16:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save frncmx/c328c85dad9a0cab2480e129acfd1ce6 to your computer and use it in GitHub Desktop.
Save frncmx/c328c85dad9a0cab2480e129acfd1ce6 to your computer and use it in GitHub Desktop.
A Bad and Good Example for Handling Goroutine shutdowns with Context
// A GOOD example for dealing with worker goroutine shutdowns
// run: https://play.golang.org/p/hdwaMQY_K9Q
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
var w worker
w.start(ctx)
time.Sleep(100 * time.Millisecond) // let worker run a little
cancel() // signal shutdown
<-w.quit // wait for shutdown
}
type worker struct {
quit chan struct{}
}
func (w *worker) start(ctx context.Context) {
w.quit = make(chan struct{})
go func() {
for {
select {
case <-ctx.Done():
w.shutdown()
return
default:
w.work()
}
}
}()
return
}
func (w *worker) shutdown() {
fmt.Println("shutdown...")
time.Sleep(1 * time.Second) // busy
fmt.Println("success...bye!") // we will see!
close(w.quit)
}
func (w *worker) work() {
fmt.Println("busy, busy...")
time.Sleep(10 * time.Millisecond)
}
// A BAD example for dealing with worker goroutine shutdowns
// run: https://play.golang.org/p/d8O01dopuHr
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
var w worker
w.start(ctx)
time.Sleep(100 * time.Millisecond) // let worker run a little
cancel() // signal shutdown
// Note: cancel() does not block. => Main exits; worker crashes.
}
type worker struct{}
func (w *worker) start(ctx context.Context) {
go func() {
for {
select {
case <-ctx.Done():
w.shutdown()
return
default:
w.work()
}
}
}()
}
func (w *worker) shutdown() {
fmt.Println("shutdown...")
time.Sleep(1 * time.Second) // busy
fmt.Println("success...bye!") // we won't see
}
func (w *worker) work() {
fmt.Println("busy, busy...")
time.Sleep(10 * time.Millisecond)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment