使用一个 "return" 值处理 goroutine 的惯用方式?
Idiomatic way of handling a goroutine with one "return" value?
想象一下我想写一个函数 returns 一个随机数除以 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)值的函数,是否有更好的惯用方法?
谢谢。
您不需要关闭频道。一旦超出范围,它将被垃圾收集。关闭频道通常用于向监听器发送 done
通知。所以在你的情况下甚至是不可能的。
您的方法是您要实现的目标的惯用方法,但不是唯一的方法。我能想到的其他一些(不一定是惯用的)是:
- 您可以使用共享数据结构并通过显式同步从多个 goroutine 填充它,
- 你可以为每个 goroutine 保留一个单独的结果,并传入一个指向它的指针。每个 goroutine 设置它的结果而不需要同步,当一切都完成后,调用者使用结果。
想象一下我想写一个函数 returns 一个随机数除以 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)值的函数,是否有更好的惯用方法?
谢谢。
您不需要关闭频道。一旦超出范围,它将被垃圾收集。关闭频道通常用于向监听器发送 done
通知。所以在你的情况下甚至是不可能的。
您的方法是您要实现的目标的惯用方法,但不是唯一的方法。我能想到的其他一些(不一定是惯用的)是:
- 您可以使用共享数据结构并通过显式同步从多个 goroutine 填充它,
- 你可以为每个 goroutine 保留一个单独的结果,并传入一个指向它的指针。每个 goroutine 设置它的结果而不需要同步,当一切都完成后,调用者使用结果。