dqyuipw44576 2019-03-19 17:22
浏览 97
已采纳

如何停止同一goroutine的多个

As it will be made obvious soon, I am a golang n00b.

I have some go code that starts goroutines based on an event channel. Say it starts 2 goroutines because we receive 2 events of type START.

The goroutine is started with an uri as parameter, which gives us something unique about it.

Later we receive one event of type STOP.

How can I stop the goroutine that was started with the same uri ?

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
                    }
                }
            }
        }
  • 写回答

1条回答 默认 最新

  • dousi6192 2019-03-19 17:41
    关注

    You cannot stop a goroutine "from the outside". You have to pass some kind of cancellation signal to each goroutine and remember them for later in the main goroutine. A Context is typically used as a cancellation signal. The goroutine then has to check for cancellation and exit voluntarily:

    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)
                }
            }
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计