http://play.golang.org/p/uRHG-Th_2P
我很难理解频道的概念
package main
import (
"fmt"
)
func Fibonacci(limit int, chnvar chan int) {
x, y := 0, 1
for i := 0; i < limit; i++ {
chnvar <- x
x, y = y, x+y
}
close(chnvar)
v, ok := <-chnvar
fmt.Println(v, ok)
}
func main() {
chn := make(chan int, 10)
go Fibonacci(cap(chn), chn)
for elem := range chn {
fmt.Printf("%v ", elem)
}
}
//1 1 2 3 5 8 13 21 34
1) 如何从行
中获取错误值v, ok := <-chnvar
如果没有更多的值可以说它是假的。 如果频道关闭,也是假的。 但在这种情况下,渠道已经关闭,但(?)仍然可以获得真正的价值。
如果我把它拿出来,就会感到恐慌。
这里如何以及为什么会返回true?
2) 这条线
go Fibonacci(cap(chn), chn)
也可以在没有goroutine的情况下运行。 有什么不同?只是表现问题。
提前致谢
答案 0 :(得分:1)
您的Fibonacci
函数将10个值填充到通道中(其缓冲区为10个值),然后将其关闭。假设在主goroutine从通道中读取所有内容之前执行v, ok <- chnvar
语句(非常可能,但不能保证),将会有一个值读取,因此ok
将为真。
如果删除close
调用,主goroutine中的for
循环将最终清空通道的缓冲区并阻塞等待更多数据。由于没有其他goroutine活动写入通道,运行时会将此检测为死锁。
您的示例程序直接调用Fibonacci
运行(而不是作为goroutine),因为它写入的通道是缓冲的,并且它永远不会超出缓冲区。因此,它可以在不阻塞的情况下完成,并允许执行继续执行main
函数的其余部分。
如果频道没有被缓冲,或者你写的值多于缓冲区中的值,那么Fibonacci
将阻止等待其他goroutine从频道中读取内容。
答案 1 :(得分:0)
<强> 1)强>
Go规范说明了频道接收操作(我的重点):
x,ok:=&lt; -ch
如果接收到的值是通过成功的发送操作传递给通道,则ok的值为true;如果由于通道关闭和为空而产生的零值,则为false。
也就是说,因为缓冲的通道不为空并且您已成功接收到值(0),ok
将为真。在渠道清空之前,您不会收到错误。
<强> 2)强>
通过在其自己的Go例程中运行Fibonacci(cap(chn), chn)
,main可以开始接收和处理(打印出)值,而Fibonacci函数仍在向通道提供新值。
在你的情况下,这可能永远不会发生,因为函数将填充缓冲区并在main有机会处理任何内容之前完成。
如果它不会在Go例程中运行,Fibonacci首先需要生成所有值,然后才能由main进一步处理。