我如何杀死一个协程

How do I kill a goroutine

我有以下设置:

func startsMain (){
    go main ()
}

fun stopMain (){
    //kill main
}

func main() {
    //infinite loop 
}

我正在创建黄瓜步骤,我需要能够启动和关闭应用程序。

您可以使用 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{}{})。它可以是 chan bool 或其他任何内容,因为我们不使用频道的内容。重要的一点是我们使用 quit 通道通知我们的 goroutine 中的无限循环是时候停止了。

select 语句用于捕获来自通道的内容。这是一个阻塞语句(它将停止执行,直到将某些内容放入 case 调查的通道之一),除非您放置 default 语句。在这种情况下,每次执行 select 时,如果在 quit 中放入了某些内容,循环就会中断,或者会调用 do_stuff()。如果您经历过 Go Tour.

,您已经知道这一点

可以在 Go Blog.

上找到其他很酷的并发模式

最后,为了更有趣,您可以使用 Tickers 要求您的 do_stuff 函数定期执行,而不是像这样消耗 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 语句。