很快就会发现,我是golang n00b。
我有一些基于事件通道启动goroutine的go代码。假设它启动了2个goroutine,因为我们收到了2个START类型的事件。
goroutine以uri作为参数开始,这给了我们一些独特之处。
稍后,我们将收到一个STOP类型的事件。
如何停止以相同uri开始的goroutine?
for { select { case event := <-eventCh: if event.Entry != nil { switch event.Action { case foo.START: log.Println("uri: ", event.Entry.URI) go func(c chan []byte, u string) error{ //awesome goroutine code }(myChan, event.Entry.URI) case foo.STOP: log.Println("uri: ", event.Entry.URI) //I'd like to terminate the goroutine that matches event.Entry.URI } } } }
您无法从外部停止goroutine。您必须将某种取消信号传递给每个goroutine,并记住它们,以备以后在main goroutine中使用。甲上下文通常被用作一个消除信号。然后,goroutine必须检查取消并自动退出:
package main import ( "context" ) type Event struct { Action string URI string } func main() { var eventCh chan Event ctx := context.Background() cancels := make(map[string]context.CancelFunc) // Maps URIs to cancellation functions. for event := range eventCh { switch event.Action { case "START": if cancels[event.URI] != nil { panic("duplicate URI: " + event.URI) } ctx, cancel := context.WithCancel(ctx) cancels[event.URI] = cancel defer cancel() // cancel must always be called to free resources. go func(u string) { // Awesome goroutine code // Check ctx.Done or ctx.Err in strategic places and return if done. select { case <-ctx.Done(): return default: } // More awesome goroutine code if ctx.Err() != nil { return } // Even more awesome goroutine code }(event.URI) case "STOP": if cancel, ok := cancels[event.URI]; ok { cancel() delete(cancels, event.URI) } } } }