【发布时间】:2020-08-04 04:13:56
【问题描述】:
我正在关注此代码以获取具有 channels
的惰性数字范围// iterator
func iterator(n int, c chan int) {
for i := 0; i < n; i++ {
c <- i
}
close(c)
fmt.Println("iterator End")
}
c := make(chan int)
go iterator(5, c)
for i := range c {
fmt.Println(i)
}
这将按预期打印
0
1
2
3
4
fmt.Println("iterator End")
但是当我像这样打破 for 循环时发生了什么
c := make(chan int)
go getNumbers(5, c)
for i := range c {
if i == 2 {
break
}
fmt.Println(i)
}
goroutine 似乎被阻塞了,因为从不打印iterator End(我也尝试让主线程休眠)。
我想知道如何处理这种情况?
我需要使用select 来解决这个问题吗?
有什么安全的方法可以检查范围是否 break 并停止迭代器中的 for-loop?
【问题讨论】:
-
make(chan int)创建一个长度为 0 的通道。这也称为无缓冲通道,这意味着对它的任何写入都将阻塞,直到发生匹配的读取。由于您在 go 例程阻塞写入时停止读取,因此它将永远阻塞该写入。解决这个问题的一个不好的方法是使用make(chan int, 2)创建一个具有足够大小来存储剩余 2 个值的通道。 (请注意,在您的代码中,您仍然从频道中读取2的int,但在打印之前是break)好的解决方案使用context.Context,如下面的答案所述。 -
“我想知道如何处理这种情况?”不要这样做。 “我需要使用 select 来解决这个问题吗?” ??? “有什么安全的方法可以检查范围是否中断并停止迭代器中的 for 循环?”没有。