如何停止goroutine

我有一个调用方法的goroutine,并将返回的值传递给一个通道:

ch := make(chan int, 100) go func(){ for { ch <- do_stuff() } }() 

我怎样才能停止这样的门厅?

编辑: 我匆匆写了这个答案,之前意识到你的问题是关于发送值在一个goroutine内的chan。 下面的方法可以使用一个额外的陈如上所述,或者使用事实上,你已经是双向的,你可以使用一个…

如果你的门厅只是为了处理陈列中的物品而存在,你可以利用“closures”内build和特殊的渠道接收表格。

也就是说,一旦你完成发送物品,你closures它。 然后在你的goroutine里面,你会得到一个额外的参数给接收操作员,显示频道是否被closures。

这是一个完整的例子(waitgroup用于确保进程继续,直到goroutine完成):

 package main import "sync" func main() { var wg sync.WaitGroup wg.Add(1) ch := make(chan int) go func() { for { foo, ok := <- ch if !ok { println("done") wg.Done() return } println(foo) } }() ch <- 1 ch <- 2 ch <- 3 close(ch) wg.Wait() } 

通常情况下,你通过goroutine(可能是单独的)信号通道。 那个信号通道是用来在你想要停止goroutine的时候把值推入。 该门厅定期对该频道进行民意调查。 一旦检测到信号,就退出。

 quit := make(chan bool) go func() { for { select { case <- quit: return default: // Do other stuff } } }() // Do stuff // Quit goroutine quit <- true 

你不能从外面杀掉一个门厅。 你可以发出一个goroutine来停止使用频道,但是没有办法处理任何元pipe理。 Goroutines的目的是合作解决问题,所以杀死一个行为不端的人几乎不会是一个适当的回应。 如果你想隔离鲁棒性,你可能需要一个过程。

我知道这个答案已经被接受了,但是我想我会把我的2英寸扔进去。我喜欢用这个墓包。 这基本上是一个加快退出渠道,但它做好事,如传回任何错误以及。 受控程序仍然有检查远程杀死信号的责任。 Afaik不可能得到一个goroutine的“id”,如果行为不当(如陷入无限循环)就杀了它。

这是我testing的一个简单的例子:

 package main import ( "launchpad.net/tomb" "time" "fmt" ) type Proc struct { Tomb tomb.Tomb } func (proc *Proc) Exec() { defer proc.Tomb.Done() // Must call only once for { select { case <-proc.Tomb.Dying(): return default: time.Sleep(300 * time.Millisecond) fmt.Println("Loop the loop") } } } func main() { proc := &Proc{} go proc.Exec() time.Sleep(1 * time.Second) proc.Tomb.Kill(fmt.Errorf("Death from above")) err := proc.Tomb.Wait() // Will return the error that killed the proc fmt.Println(err) } 

输出应该如下所示:

 # Loop the loop # Loop the loop # Loop the loop # Loop the loop # Death from above 

就个人而言,我想在一个goroutine的频道上使用范围:

http://play.golang.org/p/KjG8FLzPoz

戴夫写了一个伟大的职位关于这个: http : //dave.cheney.net/2013/04/30/curious-channels 。

一般来说,您可以创build一个频道,并在去程序中收到停止信号。

在这个例子中有两种方法来创build频道。

  1. 渠道

  2. 上下文 。 在这个例子中,我将演示context.WithCancel

第一个演示,使用channel

 package main import "fmt" import "time" func do_stuff() int { return 1 } func main() { ch := make(chan int, 100) done := make(chan struct{}) go func() { for { select { case ch <- do_stuff(): case <-done: close(ch) return } time.Sleep(100 * time.Millisecond) } }() go func() { time.Sleep(3 * time.Second) done <- struct{}{} }() for i := range ch { fmt.Println("receive value: ", i) } fmt.Println("finish") } 

第二个演示,使用context

 package main import ( "context" "fmt" "time" ) func main() { forever := make(chan struct{}) ctx, cancel := context.WithCancel(context.Background()) go func(ctx context.Context) { for { select { case <-ctx.Done(): // if cancel() execute forever <- struct{}{} return default: fmt.Println("for loop") } time.Sleep(500 * time.Millisecond) } }(ctx) go func() { time.Sleep(3 * time.Second) cancel() }() <-forever fmt.Println("finish") }