Last active
January 31, 2019 16:38
-
-
Save frncmx/c328c85dad9a0cab2480e129acfd1ce6 to your computer and use it in GitHub Desktop.
A Bad and Good Example for Handling Goroutine shutdowns with Context
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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