为了账号安全,请及时绑定邮箱和手机立即绑定

Golang:关于频道的一些问题

Golang:关于频道的一些问题

Go
长风秋雁 2021-07-09 14:09:21
http://play.golang.org/p/uRHG-Th_2P我很难理解频道的概念package mainimport (  "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如果没有更多的值要获取,它会说 false。如果通道关闭,则为 false。但在这种情况下,通道已关闭但(?)仍然获得真实值。如果我关闭,它会恐慌。它如何以及为什么在这里返回 true ?2)线路 go Fibonacci(cap(chn), chn)也可以在没有 goroutine 的情况下运行。有什么区别?只是性能问题。
查看完整描述

2 回答

?
qq_遁去的一_1

TA贡献1725条经验 获得超7个赞

  1. 您的Fibonacci函数将 10 个值填充到通道中(它有 10 个值的缓冲区),然后关闭它。假设该v, ok <- chnvar语句在主 goroutine 从通道中读取所有内容之前执行(很可能,但不能保证),将有一个值要读取,所以ok将是真的。

    如果删除close调用,for主 goroutine 中的循环最终将清空通道的缓冲区并阻塞等待更多数据。由于没有其他活跃的 goroutine 可以写入通道,运行时会将其检测为死锁。

  2. 您的示例程序Fibonacci直接调用(而不是作为 goroutine)运行,因为它写入的通道是缓冲的,并且它永远不会溢出缓冲区。因此,它可以在不阻塞的情况下完成,并允许继续执行main函数的其余部分。

    如果通道没有被缓冲,或者你写的值超过了缓冲区的容量,那么Fibonacci会阻塞等待其他 goroutine 从通道读取一些东西。


查看完整回答
反对 回复 2021-07-12
?
蓝山帝景

TA贡献1843条经验 获得超7个赞

1)

Go 规范说明了通道接收操作(我的重点):

x, 好的 := <-ch

如果接收到的值是通过成功的发送操作传递到通道,则 ok 的值为 true,如果由于通道关闭且为空而生成的零值,则值为 false 。

也就是说,因为缓冲的通道不为空并且您已成功接收到值 (0),所以ok为真。在通道清空之前,您不会收到 false。

2)

通过运行Fibonacci(cap(chn), chn)它自己的 Go 例程,main 可以开始接收和处理(打印)输出值,同时 Fibonacci 函数仍在向通道提供新值。
在您的情况下,这可能永远不会发生,因为该函数将填满缓冲区并在 main 有机会处理任何内容之前完成。

如果它不会在 Go 例程中运行,Fibonacci 将首先需要生成所有值,然后它们才能被 main 进一步处理。


查看完整回答
反对 回复 2021-07-12
  • 2 回答
  • 0 关注
  • 200 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信