duanpi7578 2017-09-11 05:24
浏览 65
已采纳

如何根据该goroutine返回的值停止goroutine

Like here I created a go playground sample: sGgxEh40ev, but cannot get it work.

quit := make(chan bool)
res := make(chan int)

go func() {
    idx := 0
    for {
        select {
        case <-quit:
            fmt.Println("Detected quit signal!")
            return
        default:
            fmt.Println("goroutine is doing stuff..")
            res <- idx
            idx++
        }
    }

}()

for r := range res {
    if r == 6 {
        quit <- true
    }
    fmt.Println("I received: ", r)
}

Output:

goroutine is doing stuff..
goroutine is doing stuff..
I received:  0
I received:  1
goroutine is doing stuff..
goroutine is doing stuff..
I received:  2
I received:  3
goroutine is doing stuff..
goroutine is doing stuff..
I received:  4
I received:  5
goroutine is doing stuff..
goroutine is doing stuff..
fatal error: all goroutines are asleep - deadlock!

Is this possible? Where am I wrong

  • 写回答

3条回答 默认 最新

  • doucai1901 2017-09-11 06:51
    关注

    The problem is that in the goroutine you use a select to check if it should abort, but you use the default branch to do the work otherwise.

    The default branch is executed if no communications (listed in case branches) can proceed. So in each iteration quit channel is checked, but if it cannot be received from (no need to quit yet), default branch is executed, which unconditionally tries to send a value on res. Now if the main goroutine is not ready to receive from it, this will be a deadlock. And this is exactly what happens when the sent value is 6, because then the main goroutine tries to send a value on quit, but if the worker goroutine is in the default branch trying to send on res, then both goroutines try to send a value, and none is trying to receive! Both channels are unbuffered, so this is a deadlock.

    In the worker goroutine you must send the value on res using a proper case branch, and not in the default branch:

    select {
    case <-quit:
        fmt.Println("Detected quit signal!")
        return
    case res <- idx:
        fmt.Println("goroutine is doing stuff..")
        idx++
    }
    

    And in the main goroutine you must break out from the for loop so the main goroutine can end and so the program can end as well:

    if r == 6 {
        quit <- true
        break
    }
    

    Output this time (try it on the Go Playground):

    goroutine is doing stuff..
    I received:  0
    I received:  1
    goroutine is doing stuff..
    goroutine is doing stuff..
    I received:  2
    I received:  3
    goroutine is doing stuff..
    goroutine is doing stuff..
    I received:  4
    I received:  5
    goroutine is doing stuff..
    goroutine is doing stuff..
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 Pwm双极模式H桥驱动控制电机
  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题