gpt4 book ai didi

go - 如何根据 goroutine 的返回值停止 goroutine

转载 作者:IT王子 更新时间:2023-10-29 00:57:57 25 4
gpt4 key购买 nike

像这里一样,我创建了一个 go playground 示例:sGgxEh40ev ,但无法正常工作。

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)
}

输出:

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!

这可能吗?我哪里错了

最佳答案

问题在于,在 goroutine 中,您使用 select 来检查它是否应该中止,但您使用 default 分支来完成其他工作。

如果没有通信(在case 分支中列出)可以继续进行,则执行default 分支。所以在每次迭代中检查 quit channel ,但如果无法从中接收到它(还不需要退出),则执行 default 分支,无条件地 尝试在 res 上发送一个值。现在如果 main goroutine 还没有准备好接收它,这将是一个死锁。这正是发送的值为 6 时发生的情况,因为主 goroutine 会尝试在 quit 上发送一个值,但是如果 worker goroutine 在 >default 分支尝试在 res 上发送,然后 两个 goroutine 都尝试发送一个值,但没有一个尝试接收!两个 channel 都没有缓冲,所以这是一个死锁。

在 worker goroutine 中,您必须使用适当的 case 分支在 res 上发送值,而不是在 default 分支中:

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

在主 goroutine 中,你必须跳出 for 循环,这样主 goroutine 才能结束,程序也能结束:

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

这次输出(在 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..

关于go - 如何根据 goroutine 的返回值停止 goroutine,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46148682/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com