go - How can I stop the goroutine based on the returned value from that goroutine -
like here created go playground sample: sggxeh40ev, cannot work.
quit := make(chan bool) res := make(chan int) go func() { idx := 0 { select { case <-quit: fmt.println("detected quit signal!") return default: fmt.println("goroutine doing stuff..") res <- idx idx++ } } }() r := range res { if r == 6 { quit <- true } fmt.println("i received: ", r) }
output:
goroutine doing stuff.. goroutine doing stuff.. received: 0 received: 1 goroutine doing stuff.. goroutine doing stuff.. received: 2 received: 3 goroutine doing stuff.. goroutine doing stuff.. received: 4 received: 5 goroutine doing stuff.. goroutine doing stuff.. fatal error: goroutines asleep - deadlock!
is possible? wrong
the problem in goroutine use select
check if should abort, use default
branch work otherwise.
the default
branch executed if no communications (listed in case
branches) can proceed. in each iteration quit
channel checked, if cannot received (no need quit yet), default
branch executed, unconditionally tries send value on res
. if main goroutine not ready receive it, deadlock. , happens when sent value 6
, because main goroutine tries send value on quit
, if worker goroutine in default
branch trying send on res
, both goroutines try send value, , none trying receive! both channels unbuffered, deadlock.
in worker goroutine must send value on res
using proper case
branch, , not in default
branch:
select { case <-quit: fmt.println("detected quit signal!") return case res <- idx: fmt.println("goroutine doing stuff..") idx++ }
and in main goroutine must break out for
loop main goroutine can end , program can end well:
if r == 6 { quit <- true break }
output time (try on go playground):
goroutine doing stuff.. received: 0 received: 1 goroutine doing stuff.. goroutine doing stuff.. received: 2 received: 3 goroutine doing stuff.. goroutine doing stuff.. received: 4 received: 5 goroutine doing stuff.. goroutine doing stuff..
Comments
Post a Comment