gpt4 book ai didi

go - 缓冲 channel 并关闭它

转载 作者:数据小太阳 更新时间:2023-10-29 03:31:36 26 4
gpt4 key购买 nike

我有一段代码,我试图根据我如何放置 close 调用和位置来理解它

func main() {
ch := make(chan int, 2)

go func(ch chan int) {
for i := 1; i <= 5; i++ {
ch <- i
fmt.Println("Func goroutine sends data: ", i)
}
//Pos1 - Works perfectly
//close(ch)
}(ch)

fmt.Println("Main goroutine sleeps 2 seconds")
time.Sleep(time.Second * 2)

fmt.Println("Main goroutine begins receiving data")
//Pos2 - Puts in only 2 ints 1 and 2 and then prints only that
//close(ch)
for d := range ch {
fmt.Println("Main goroutine received data:", d)
}
//Pos3 - Throws fatal error
close(ch)
}

我一直在尝试理解和阅读关于此的博客,但仍然无法理解某些东西

  1. 当我在 Pos1 处收盘时,效果很好。但我不确定为什么有用。缓冲区在任何给定的情况下都不能容纳超过 2 个元素时间,所以当写入 2 个元素时,循环将阻塞直到主路由进行读取。但我想做一个范围缓冲 channel ,范围函数必须事先知道有多少要迭代的元素和该 channel 的元素必须关闭。为什么close 在这个位置工作吗?
  2. 当我把它放在位置 2 时,它只打印 2 个元素,这是有道理的,但为什么 for 循环 在尝试向 channel 写入更多元素时没有抛出异常关门了吗?
  3. 当我在 Pos3 关闭时,我得到一个异常fatal error: all goroutines are asleep - deadlock! 尽管所有 5 个整数都被打印出来了。这是为什么?

最佳答案

But I thought to do a range over a buffered channel, the range function has to know beforehand how many elements to iterate over and for that channel must be closed. 

这个假设是错误的,也是所有误解的根源。

Go 规范中描述了在 channel 上测距的行为:https://golang.org/ref/spec#For_statements

For channels, the iteration values produced are the successive values sent on the channel until the channel is closed. If the channel is nil, the range expression blocks forever.

for语句执行时不需要关闭 channel ,语句不需要知道元素个数。

因此,在您的代码中,当您将 close 放在 Pos1 中时,这确实是正确的做法。当你把它放在 Pos3 中时,for 循环等待 channel 关闭,这只能发生在 for 循环本身之后,所以它是一个死锁。

close 放在 Pos2 中是有问题的,而且行为有点棘手。 可能 引发错误,但也可能只输出两个数字。这是因为当 channel 在 for 循环之前关闭时,循环可以无阻塞地运行,然后 main() 返回。当 main() 返回时,Go 程序结束。它是否引发错误完全取决于调度程序是否在进程之间切换到 goroutine,这是无法保证的。

关于go - 缓冲 channel 并关闭它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50980577/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com