最新公告
  • 欢迎您光临码农资源网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!加入我们
  • 终止无限循环 goroutine 的安全方法?

    终止无限循环 goroutine 的安全方法?

    问题内容

    我有一个充当侦听器的 goroutine。输入流传入某个缓冲的 channel,我希望我的 goroutine 处理传入该通道的数据。然而,有时 channel 可能会暂时没有数据输入。如果 channel 一秒钟没有什么可提供的,我希望我的 goroutine 做一些不同的事情。该函数如下所示:

    func main () {
        var wg sync.WaitGroup
        arr := make([]*myObject, 0)
        wg.Add(1)
        go listener(c, arr, &wg)
        for {
            // sending stuff to c
        }
    }
    
    func listener(c chan *myObject, arr []*myObject, wg *sync.WaitGroup) {
        for {
            select {
            case value := <- c:
                arr = append(arr, value)
            case <- time.After(1 * time.Second):
                fmt.Println(arr)
            }
    }

    问题是我想看到通过该通道的所有内容都打印出来。如果 main 突然结束,可能 arr 中还剩下一些东西还没有打印出来,我就看不到了。所以我需要确保这个goroutine在程序结束之前处理完通道中的所有数据。我认为,这意味着我需要使用 WaitGroup 并使用 Wait() 来确保程序在我的 goroutine 完成需要执行的操作之前不会关闭。 但我不知道在我的 WaitGroup 上调用 Done() 的位置。

    基本上,我需要一种安全的方法来在程序结束之前“暂停”goroutine,并打印出剩下的内容。我怎样才能做到这一点?

    更糟糕的是,对于单元测试之类的事情,我自己将数据发送到通道,在发送一定数量后,我想查看数组。但是,如果我只是在将数据发送到通道的代码之后立即检查数组,则 goroutine 可能还没有机会处理所有数据。在这种情况下,我想等待 goroutine 处理我发送的所有数据,然后我想暂停它并要求它向我显示数组。但我如何知道 goroutine 何时完成处理呢?我可以 sleep 一段时间,给它一个完成的机会,然后停下来看看,但这感觉相当黑客。我认为有一个最佳实践方法可以解决这个问题,但我还没有弄清楚。

    这是我的一些想法,其中零个有效。

    1. 在无限 for 循环之外调用 Done()。这不起作用,因为据我所知,该代码无法访问。

    2. 在超时case中调用Done()。这是行不通的,因为超时后可能会有更多数据在路上,我希望我的 goroutine 继续监听。

    正确答案

    修改侦听器以在通道关闭时返回。返回时调用 wg.Done():

    func listener(c chan *myObject, arr []*myObject, wg *sync.WaitGroup) {
        defer wg.Done()
        for {
            select {
            case value, ok := <- c:
                if !ok { return }
                arr = append(arr, value)
            case <- time.After(1 * time.Second):
                fmt.Println(arr)
            }
    }

    修改 main 以在发送完成后关闭通道。在从 main 返回之前等待 goroutine 完成。

    var wg sync.WaitGroup
    arr := make([]*myObject, 0)
    wg.Add(1)
    go listener(c, arr, &wg)
    for {
        // sending stuff to c
    }
    close(c)
    wg.Wait()
    想要了解更多内容,请持续关注码农资源网,一起探索发现编程世界的无限可能!
    本站部分资源来源于网络,仅限用于学习和研究目的,请勿用于其他用途。
    如有侵权请发送邮件至1943759704@qq.com删除

    码农资源网 » 终止无限循环 goroutine 的安全方法?
    • 7会员总数(位)
    • 25846资源总数(个)
    • 0本周发布(个)
    • 0 今日发布(个)
    • 293稳定运行(天)

    提供最优质的资源集合

    立即查看 了解详情