Golang:有关通道的一些问题

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

Golang : some questions on channel

问题

我现在是你的中文翻译助手,以下是翻译好的内容:

如何从以下代码中的这一行获取 false 值:

v, ok := <-chnvar

如果没有更多的值可获取,它会返回 false。
如果通道已关闭,它也会返回 false。
但在这种情况下,通道已关闭,但仍然返回 true 值。

如果我去掉 close,它会引发 panic。

为什么在这里会返回 true 值?如何解释这个现象?

这一行代码

go Fibonacci(cap(chn), chn)

即使不使用 goroutine 也可以运行。
有什么区别?只是性能上的差异吗?

提前感谢你的回答。

英文:

http://play.golang.org/p/uRHG-Th_2P

I am having hard time understanding the concept of channel

package main

import (
  &quot;fmt&quot;
)

func Fibonacci(limit int, chnvar chan int) {
  x, y := 0, 1
  for i := 0; i &lt; limit; i++ {
    chnvar &lt;- x
    x, y = y, x+y
  }
  close(chnvar)

  v, ok := &lt;-chnvar
  fmt.Println(v, ok)
}


func main() {
  chn := make(chan int, 10)
  go Fibonacci(cap(chn), chn)
  for elem := range chn {
    fmt.Printf(&quot;%v &quot;, elem)
  }
}
//1 1 2 3 5 8 13 21 34 

How do I get false value from the line

v, ok := &lt;-chnvar

It says false if there are no more values to get.
and also false if the channel is closed.
But in this case, the channel is closed but(?) still get the true value.

And if I take out the close, it panics.

How and why it returns true here?

2)
The line

 go Fibonacci(cap(chn), chn)

also runs without goroutine.
What is the difference? Just matter of performance.

Thanks in advance

答案1

得分: 1

你的Fibonacci函数将10个值放入通道(该通道具有10个值的缓冲区),然后关闭它。假设在主goroutine读取通道中的所有内容之前,v, ok <- chnvar语句执行,那么将有一个值可供读取,因此ok将为true。

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

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

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

英文:
  1. Your Fibonacci function stuffs 10 values into the channel (which has a buffer of 10 values), and then closes it. Assuming the v, ok &lt;- chnvar statement executes before the main goroutine reads everything out of the channel (very likely, but not guaranteed), there will be a value to read so ok will be true.

    If you remove the close call, the for loop in the main goroutine will eventually empty the channel's buffer and block waiting for more data. Since there is no other goroutine active to write to the channel, the runtime detects this as a deadlock.

  2. Your sample program runs with Fibonacci called directly (not as a goroutine) because the channel it writes to is buffered, and it never overruns the buffer. Therefore it can complete without blocking and allows execution to continue to the rest of the main function.

    If the channel was not buffered, or you wrote more values than would fit in the buffer, then Fibonacci would block waiting for some other goroutine to read something from the channel.

答案2

得分: 0

1)

根据Go规范,对于通道接收操作(我强调):

x, ok := <-ch

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

也就是说,因为缓冲通道不为空,并且你成功接收到一个值(0),所以ok的值为true。只有在通道被清空之后,你才会接收到false。

2)

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

如果不在Go协程中运行,Fibonacci函数首先需要生成所有的值,然后才能由主函数进一步处理。

英文:

1)

The Go specification states for channel receive operations (my emphasis):

>x, ok := <-ch
>
>The value of ok is true if the value received was delivered by a successful send operation to the channel, or false if it is a zero value generated because the channel is closed and empty.

That is, because the buffered channel is not empty and you have successfully received a value (0), ok will be true. You won't receive false until the channel has been emptied.

2)

By running the Fibonacci(cap(chn), chn) in it's own Go routine, main can start receiving and processing (printing out) out values while the Fibonacci function is still feeding new values to the channel.
In your case, this probably never happens since the function will have filled up the buffer and completed before main gets a chance to process anything.

If it would not be running in a Go routine, Fibonacci would first need to produce all the values before they can be processed further by main.

huangapple
  • 本文由 发表于 2013年11月21日 14:21:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/20113876.html
匿名

发表评论

匿名网友

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

确定