使用通道在Go语言中实现斐波那契数列

huangapple go评论76阅读模式
英文:

Fibonacci in Go using channels

问题

我正在遵循tour.golang.org上的示例。

我大部分理解这个示例,唯一的问题是为什么当我们向quit通道传递0时它会停止?无论是否将0传递给quit,x始终有一个值。所以选择语句不应该总是执行case 'c <- x'吗?

func fibonacci(c chan int, quit chan int) {
    x, y := 0, 1
    for {
        select {
        case c <- x:
            x, y = y, x+y
        case <-quit:
            return
        }
    }
    close(c)
}

func main() {
    c := make(chan int)
    quit := make(chan int)
    go func() {
        for i := 0; i < 10; i++ {
            fmt.Println(<-c)
        }
        quit <- 0
    }()
    fibonacci(c, quit)
}
英文:

I am following the examples on tour.golang.org.

I understand the example mostly, the only issue I have is why does it stop when we pass 0 to quit channel? Regardless of whether 0 was passed to quit, there is always a value for x. So shouldn't select always fall on case 'c <- x' ?

func fibonacci(c chan int, quit chan int) {
	x, y := 0, 1
	for {
		select {
		case c &lt;- x:
			x, y = y, x+y
		case &lt;-quit:
			return
		}
	}
	close(c)
}

func main() {
	c := make(chan int)
	quit := make(chan int)
	go func() {
		for i := 0; i &lt; 10; i++ {
			fmt.Println(&lt;-c)
		}
		quit &lt;- 0
	}()
	fibonacci(c, quit)
}

答案1

得分: 2

不,因为这个通道是无缓冲的,发送操作会一直阻塞,直到有接收者可以接收数据。

在《Effective Go》中了解有关通道的内容:

接收者总是会阻塞,直到有数据可接收。**如果通道是无缓冲的,发送者会阻塞,直到接收者接收到值。**如果通道有缓冲区,发送者只会阻塞,直到值被复制到缓冲区;如果缓冲区已满,这意味着等待直到某个接收者取走一个值。

此外,如果在 select 语句中有两个 case 可以执行,会通过伪随机选择一个

如果一个或多个通信可以进行,将通过均匀的伪随机选择选择一个可以进行的通信。否则,如果有默认 case,将选择该 case。如果没有默认 case,则 "select" 语句将阻塞,直到至少有一个通信可以进行。

英文:

> there is always a value for x. So shouldn't select always fall on case 'c <- x' ?

No, because this channel is unbuffered, the send will block until someone can receive from it.

Read about channels on Effective Go:

> Receivers always block until there is data to receive. If the channel is unbuffered, the sender blocks until the receiver has received the value. If the channel has a buffer, the sender blocks only until the value has been copied to the buffer; if the buffer is full, this means waiting until some receiver has retrieved a value.

Additionally, if 2 cases in a select statement could proceed, one is picked pseudo-randomly.

> If one or more of the communications can proceed, a single one that can proceed is chosen via a uniform pseudo-random selection. Otherwise, if there is a default case, that case is chosen. If there is no default case, the "select" statement blocks until at least one of the communications can proceed.

huangapple
  • 本文由 发表于 2015年6月5日 19:50:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/30665829.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定