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 android报错 brut.common.BrutException: could not exec (exit code = 1)
  • ¥15 nginx反向代理获取ip,java获取真实ip
  • ¥15 eda:门禁系统设计
  • ¥50 如何使用js去调用vscode-js-debugger的方法去调试网页
  • ¥15 376.1电表主站通信协议下发指令全被否认问题
  • ¥15 物体双站RCS和其组成阵列后的双站RCS关系验证
  • ¥15 复杂网络,变滞后传递熵,FDA
  • ¥20 csv格式数据集预处理及模型选择
  • ¥15 部分网页页面无法显示!
  • ¥15 怎样解决power bi 中设置管理聚合,详细信息表和详细信息列显示灰色,而不能选择相应的内容呢?