英文:
Buffered channel close TRUE?
问题
我有一些问题...关于缓冲通道
问题1:
为什么非缓冲通道(NonBuffered)从未输出过TRUE值?
这是否意味着非缓冲通道总是关闭的?
那么为什么非缓冲通道仍然能产生正确的斐波那契计算结果?
问题2:
为什么非缓冲通道的输出会像下面这样被截断?
0 1 1 2 NB value: 0
NB ok: false
3
这应该与goroutine有关,但为什么会以这种方式呢?
很难理解,因为如果我给这个通道加上缓冲,我会得到TRUE值,但是使用非缓冲通道我只能得到FALSE值...
请查看以下链接。
http://play.golang.org/p/O2Th61DfEY
package main
import "fmt"
func main() {
ch := make(chan int)
go NB(5, ch)
for i := range ch {
fmt.Printf("%d ", i)
}
/*
0 1 1 2 NON_Buffered value: 0
NON_Buffered ok: false
3
*/
fmt.Println()
value, ok := <-ch
fmt.Println("MAIN = NB value:", value)
fmt.Println("MAIN = NB ok:", ok)
}
func NB(n int, ch chan int) {
x, y := 0, 1
for i := 0; i < n; i++ {
ch <- x
x, y = y, x+y
}
close(ch)
value, ok := <-ch
fmt.Println("NB value:", value)
fmt.Println("NB ok:", ok)
}
非常感谢!
英文:
I have some questions... on Buffered Channel
Q1.
Then why the NonBuffered never outputs the TRUE value?
Does this mean the unbuffered channel is always closed?
Then how come the unbuffered channel still produce the right outcome of fibonacci calculation?
Q2.
Why the NonBuffered output gets cut in the middle like the following?
0 1 1 2 NB value: 0
NB ok: false
3
It should be something related with goroutine but Why in this way?
It is hard to understand because if I buffer this channel I get true value but with unbuffered channel I get only false...
Please check out the following link.
http://play.golang.org/p/O2Th61DfEY
package main
import "fmt"
func main() {
ch := make(chan int)
go NB(5, ch)
for i := range ch {
fmt.Printf("%d ", i)
}
/*
0 1 1 2 NON_Buffered value: 0
NON_Buffered ok: false
3
*/
fmt.Println()
value, ok := <-ch
fmt.Println("MAIN = NB value:", value)
fmt.Println("MAIN = NB ok:", ok)
}
func NB(n int, ch chan int) {
x, y := 0, 1
for i := 0; i < n; i++ {
ch <- x
x, y = y, x+y
}
close(ch)
value, ok := <-ch
fmt.Println("NB value:", value)
fmt.Println("NB ok:", ok)
}
Thanks a lot!
答案1
得分: 1
Q1: 在未关闭的通道上,你从未执行过 value, ok <- ch
这个操作:在 NB 中,你在关闭 ch
之后执行这个语句,在主函数中,你在 for 循环中从 ch
中读取完所有值之后执行这个语句。为什么你期望返回 ok==true
来表示通道未关闭?
Q2: 一旦在主函数中从 ch
中消费了 3,NB 可能会再次运行并在主函数开始打印之前打印。NB 和主函数之间完全没有同步。再次强调:你对这样的代码有什么期望?
如果你想模拟生成斐波那契数列的生成器,你不应该从 ch
中读取。这与缓冲无关。缓冲通道只是允许某些 goroutine 在阻塞在通道发送操作之前执行更长时间的操作。
英文:
Q1: You never do value, ok <- ch
on an un-closed channel: in NB you execute this statement after closing ch
, and in main you execute it after reading all from ch in the for loop. Why do you expect to ever return ok==true
to indicate the channel is un-closed?
Q2: Once 3 is consumed from ch in main NB may run again and print before main starts printing. You have absolutely no synchronization between NB and main. Again: What do you expect from such code?
If you want to emulate a generator for fibonacci numbers you should not read in NB from ch. This has nothing to do with buffering. Buffered channels just allow some goroutines to execute longer before blocking on the channel send.
答案2
得分: 0
这是由于channel Close操作的工作方式导致的。输出中最有趣的部分是对于缓冲的、NB ok(非MAIN版本)为true
,但VB值仍为0。它返回0是因为它已经关闭,但由于尚未读取所有的值,它尚未被耗尽(所有发送的值都已被接收)。我不确定输出为什么会以不同的顺序排列 - 我认为这是非确定性的。
然而,@Volker的答案可能更有用。尽管有趣,但您的程序存在一些错误。
英文:
This is do to how the channel Close operation works. The most interesting part of the output is that for the buffered, NB ok (the non-MAIN version) is true
, but the VB value is still 0. It's returning 0 because it's closed, but since all the values haven't yet been read, it's not drained (all sent values have been received). I'm not sure about why the output orders differently - I think it's non deterministic.
However, @Volker's answer is probably the more useful one. Your program is doing a number of things incorrectly, albeit interesting.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论