我有以下设置:
func startsMain (){ go main () } fun stopMain (){ //kill main } func main() { //infinite loop }
我正在创建黄瓜步骤,我需要能够启动和关闭该应用程序。
您可以使用select和频道杀死无限循环!
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中的无限循环,该该停止了。
chan struct{}
struct{}{}
chan bool
quit
该select语句用于捕获来自渠道的内容。这是一条阻塞语句(case除非您放置一条default语句,否则它将停止执行,直到在所调查的通道之一中放入某些内容为止)。在这种情况下,每次select执行时,如果将某些内容放入quit或do_stuff()将被调用,则循环将中断。如果您去过Go Tour,那么您已经知道这一点。
case
default
do_stuff()
其他很酷的并发模式可以在Go Blog中找到。
最后,为了获得更多的乐趣,您可以do_stuff使用Tickers 来要求您的函数在固定的时间间隔执行,而不是像这样消耗100%的CPU:
do_stuff
Ticker
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语句,因此此处处于阻塞状态。