处理具有一个“返回”值的goroutine的惯用方式?

问题描述 投票:-2回答:1

想象我想编写一个返回随机数除以2的函数:

func randomIntInHalf() int {
    return rand.Int() / 2
}

但是后来我决定要为并发构建此函数,所以最终得到:

func randomIntInHalf(c chan<- int) {
    c <- rand.Int() / 2
}

func main() {
    // Generate 10 random ints in parallel
    amount := 10
    c := make(chan int, amount)

    for i := 0; i < amount; i++ {
        go randomIntInHalf(c)
    }

    for i := 0; i < amount; i++ {
        fmt.Println(<-c)
    }

    close(c)
}

我看到这种方法的一些问题。例如,我要求调用者在完成生成后关闭通道,从而使某人可能会调用该函数并使通道无限期地保持打开状态。我的理解是,您始终希望发件人关闭频道。 a)是真的,b)在这种情况下甚至可能吗?有没有更好的方法来编写此代码或解决此问题?

而且,通常,有更好的惯用方法用于并行运行一个仅向通道写入1(或已知N)值的函数?

谢谢。

go channels
1个回答
2
投票

您不需要关闭频道。一旦超出范围,将被垃圾回收。关闭通道通常用于向侦听器发送done通知。因此,根据您的情况,甚至是不可能的。

您是您要达到的目标的惯用方法,但不是唯一的方法。我可以想到的其他一些(不一定是惯用的)是:

  • 您可以使用共享的数据结构,并通过显式同步从多个goroutine中填充它,
  • 您可以为每个goroutine保留一个单独的结果,并传递一个指向它的指针。每个goroutine都无需同步就可以设置其结果,完成所有操作后,调用者便可以处理结果。
© www.soinside.com 2019 - 2024. All rights reserved.