gpt4 book ai didi

go - 当没有 channel 准备好被读取时如何什么都不做?

转载 作者:IT王子 更新时间:2023-10-29 01:27:22 26 4
gpt4 key购买 nike

让我们以 GoTour 中的这个例子为例,因为它说明了我的问题,即仅在有事件发生时才处理 SDL 事件。

package main

import (
"fmt"
"time"
)

func main() {
tick := time.Tick(1e8)
boom := time.After(5e8)
for {
select {
case <-tick:
fmt.Println("tick.")
case <-boom:
fmt.Println("BOOM!")
return
default:
fmt.Println(" .")
time.Sleep(5e7)
}
}
}

这行得通。但是,如果我不想在默认情况下打印或休眠,只想一直循环怎么办?我试过这个:

    case <-boom:
fmt.Println("BOOM!")
return
default: // Nothing here.
}
}
}

但它会阻塞。

我在这里和那里看到过关于goroutines调度的一句话,但我没看懂。所以我想我有两个问题:

1) 为什么会阻塞?

2) 如何让它在不阻塞的情况下什么都不做?

最佳答案

Your Original Example产生这个

    .
.
tick.
.
.
tick.
.
.
tick.
.
.
tick.
.
.
tick.
BOOM!

Wheraeas Your Second Example产生这个

[process took too long]

不同之处在于您在 default 情况下所做的事情。 default 案例总是准备好运行,因此带有 default 语句的 select 永远不会阻塞。第二个示例循环运行,不断选择准备运行的分支之一(case 或 default)。您现在想知道为什么计时器从不触发。那是因为 go routines 不是预先安排的。因此,因为下面的循环从不执行任何 IO,所以时间滴答从不触发。

for {
select {
// whatever
default:
}
}

有很多方法可以解决这个问题。首先,您可以像在第一个示例中那样放入一些 IO。或者你可以放一个 runtime.Gosched()或者你可以允许 go 运行时使用多个线程 runtime.GOMAXPROCS(2)所有这些都会起作用。

恕我直言,最好的方法是完全省略默认语句 like this .没有 default 语句的 select 将阻塞,直到其中一个 case 语句准备就绪。如果你想做一些后台处理(你在默认语句中做的)然后启动一个 goroutine - 这就是 go 方式!

事实上,我在 select 语句中看到了太多关于 default 的问题,我很想说永远不要使用它们。

关于go - 当没有 channel 准备好被读取时如何什么都不做?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14633373/

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