【问题标题】:Idiomatic way of handling a goroutine with one "return" value? [closed]处理具有一个“返回”值的 goroutine 的惯用方式? [关闭]
【发布时间】:2020-02-19 19:57:50
【问题描述】:

假设我想编写一个返回随机数除以 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)值的函数?

谢谢。

【问题讨论】:

  • A) No. B) 写一个普通函数。如果您坚持通过渠道传递价值,那么您的方法很好,因为 A。如果您不在渠道范围内,则没有真正需要关闭它。

标签: go channels


【解决方案1】:

您不需要关闭频道。一旦超出范围,它将被垃圾收集。关闭通道通常用于向监听器发送done 通知。所以在你的情况下甚至是不可能的。

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

  • 您可以使用共享数据结构并通过显式同步的多个 goroutine 填充该结构,
  • 您可以为每个 goroutine 保留一个单独的结果,并传入一个指向它的指针。每个 goroutine 设置它的结果而不需要同步,当一切都完成后,调用者处理结果。

【讨论】:

  • 我不会将这些方法称为“惯用的”。来自 Effective Go (golang.org/doc/effective_go.html#concurrency):Go encourages a different approach in which shared values are passed around on channels and, in fact, never actively shared by separate threads of execution.
  • @EmilePels 公平点。在答案中指出。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-10
  • 1970-01-01
  • 2013-06-15
  • 2017-03-01
  • 2017-10-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多