douguachan2879 2017-12-19 01:57
浏览 32
已采纳

在一定时间内从goroutine接收值

I have a goroutine which can generate an infinite number of values (each more suitable than the last), but it takes progressively longer to find each values. I'm trying to find a way to add a time limit, say 10 seconds, after which my function does something with the best value received so far.

This is my current "solution", using a channel and timer:

// the goroutine which runs infinitely
// (or at least a very long time for high values of depth)
func runSearch(depth int, ch chan int) {
    for i := 1; i <= depth; i++ {
        fmt.Printf("Searching to depth %v
", i)
        ch <- search(i)
    }
}

// consumes progressively better values until the channel is closed
func awaitBestResult(ch chan int) {
    var result int
    for result := range ch {
        best = result
    }

    // do something with best result here
}

// run both consumer and producer
func main() {
    timer := time.NewTimer(time.Millisecond * 2000)

    ch := make(chan int)

    go runSearch(1000, ch)
    go awaitBestResult(ch)

    <-timer.C
    close(ch)
}

This mostly works - the best result is processed after the timer ends and the channel is closed. However, I then get a panic (panic: send on closed channel) from the runSearch goroutine, since the channel has been closed by the main function.

How can I stop the first goroutine running after the timer has completed? Any help is very appreciated.

  • 写回答

2条回答 默认 最新

  • doudao1837 2017-12-19 09:06
    关注

    You need to ensure that the goroutine knows when it is done processing, so that it doesn't attempt to write to a closed channel, and panic.

    This sounds like a perfect case for the context package:

    func runSearch(ctx context.Context, depth int, ch chan int) {
        for i := 1; i <= depth; i++ {
            select {
            case <- ctx.Done()
                // Context cancelled, return
                return
            default:
            }
            fmt.Printf("Searching to depth %v
    ", i)
            ch <- search(i)
        }
    }
    

    Then in main():

    // run both consumer and producer
    func main() {
        ctx := context.WithTimeout(context.Background, 2 * time.Second)
    
        ch := make(chan int)
    
        go runSearch(ctx, 1000, ch)
        go awaitBestResult(ch)
    
        close(ch)
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥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和热敏电阻的数字温度计