mirror of
https://github.com/crazybber/awesome-patterns.git
synced 2024-11-24 21:46:03 +03:00
finished using cancel signal to terminate goroutine
This commit is contained in:
parent
08e01c5a9c
commit
dc703eecec
@ -1,6 +1,11 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
)
|
||||
|
||||
// The goroutine has a few paths to termination:
|
||||
// • When it has completed its work.
|
||||
@ -15,7 +20,7 @@ goroutines in some sort of organized fashion.
|
||||
**/
|
||||
|
||||
func main() {
|
||||
|
||||
cancellationSignal()
|
||||
}
|
||||
|
||||
// Here we see that the main goroutine passes a nil channel into doWork. Therefore, the
|
||||
@ -44,6 +49,46 @@ func resourceLeak() {
|
||||
fmt.Println("Done.")
|
||||
}
|
||||
|
||||
// The way to successfully mitigate this is to establish a signal between the parent gorou‐
|
||||
// tine and its children that allows the parent to signal cancellation to its children. By
|
||||
// convention, this signal is usually a read-only channel named done. The parent gorou‐
|
||||
// tine passes this channel to the child goroutine and then closes the channel when it
|
||||
// wants to cancel the child goroutine. Here’s an example:
|
||||
func cancellationSignal() {
|
||||
|
||||
// Here we pass the done channel to the doWork function. As a convention, this channel is the first parameter.
|
||||
doWork := func(
|
||||
done <-chan interface{},
|
||||
strings <-chan string,
|
||||
) <-chan interface{} {
|
||||
terminated := make(chan interface{})
|
||||
go func() {
|
||||
defer fmt.Println("doWork exited.")
|
||||
defer close(terminated)
|
||||
for {
|
||||
select {
|
||||
case s := <-strings:
|
||||
fmt.Println(s)
|
||||
// On this line we see the ubiquitous for-select pattern in use. One of our case statements
|
||||
// is checking whether our done channel has been signaled. If it has, we return from the goroutine.
|
||||
case t := <-done:
|
||||
spew.Dump(t)
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
return terminated
|
||||
}
|
||||
done := make(chan interface{})
|
||||
terminated := doWork(done, nil)
|
||||
// Here we create another goroutine that will cancel the goroutine spawned in
|
||||
// doWork if more than one second passes.
|
||||
go func() {
|
||||
// Cancel the operation after 1 second.
|
||||
time.Sleep(1 * time.Second)
|
||||
fmt.Println("Canceling doWork goroutine...")
|
||||
close(done)
|
||||
}()
|
||||
// This is where we join the goroutine spawned from doWork with the main goroutine.
|
||||
<-terminated
|
||||
fmt.Println("Done.")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user