您可以使用select
和频道杀死无限循环!
var quit chan struct{}
func startLoop() {
quit := make(chan struct{})
go loop()
}
func stopLoop() {
// As mentioned by Kaedys
//close(quit)
// permits signalling everyone havins such a `case <-quit:`
// statement to be stopped at once, which might be even better.
quit <- struct{}{}
}
// BTW, you cannot call your function main, it is reserved
func loop() {
for {
select {
case <-quit:
return # better than break
default:
// do stuff. I'd call a function, for clarity:
do_stuff()
}
}
}
很不错的Go交换,不是吗?
现在,这有什么奇怪的地方chan struct{}
?这是一个零尺寸的频道。我们只能用空结构填充它(即:)struct{}{}
。可能是a chan bool
或其他,因为我们不使用频道的内容。重要的是,我们使用quit
通道通知goroutine中的无限循环,该该停止了。
该select
语句用于捕获来自渠道的内容。这是一条阻塞语句(case
除非您放置一条default
语句,否则它将停止执行,直到在所调查的通道之一中放入某些内容为止)。在这种情况下,每次select
执行时,如果将某些内容放入quit
或do_stuff()
将被调用,则循环将中断。如果您去过Go Tour,那么您已经知道这一点。
其他很酷的并发模式可以在Go Blog中找到。
最后,为了获得更多的乐趣,您可以do_stuff
使用Ticker
s 来要求您的函数在固定的时间间隔执行,而不是像这样消耗100%的cpu:
import "time"
// [...]
func loop() {
// This ticker will put something in its channel every 2s
ticker := time.NewTicker(2 * time.Second)
// If you don't stop it, the ticker will cause memory leaks
defer ticker.Stop()
for {
select {
case <-quit:
return
case <-ticker.C:
// do stuff. I'd call a function, for clarity:
do_stuff()
}
}
}
select
由于我们删除了该default
语句,因此此处处于阻塞状态。