【问题标题】:Golang : some questions on channelGolang:关于频道的一些问题
【发布时间】:2013-12-05 12:06:15
【问题描述】:

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

如果没有更多的值可以获取,它会显示为 false。 如果通道关闭,也是错误的。 但是在这种情况下,通道是关闭的,但是(?)仍然得到了真正的价值。

如果我取消收盘价,它就会恐慌。

它如何以及为什么在这里返回 true?

2) 线

 go Fibonacci(cap(chn), chn)

也可以在没有 goroutine 的情况下运行。 有什么区别?只是性能问题。

提前致谢

【问题讨论】:

    标签: recursion concurrency go fibonacci channel


    【解决方案1】:
    1. 您的Fibonacci 函数将 10 个值填充到通道中(该通道具有 10 个值的缓冲区),然后将其关闭。假设 v, ok &lt;- chnvar 语句在主 goroutine 从通道中读取所有内容之前执行(很可能,但不能保证),将会有一个值要读取,所以 ok 将为真。

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

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

      如果通道没有缓冲,或者你写入的值超出了缓冲区的容量,那么Fibonacci 将阻止等待其他一些 goroutine 从通道中读取内容。

    【讨论】:

      【解决方案2】:

      1)

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

      x,好的:=

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

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

      2)

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

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

      【讨论】:

        猜你喜欢
        • 2020-02-02
        • 1970-01-01
        • 2021-07-29
        • 1970-01-01
        • 2018-05-24
        • 2013-07-07
        • 2013-05-10
        • 2012-03-18
        • 2023-03-09
        相关资源
        最近更新 更多