c:= make(chan int)和c:= make(chan int,1)之间的区别是什么?

时间:2014-04-23 01:45:51

标签: go channel

我认为它们是相同的,但The go memory model中有这样的字:如果频道被缓冲(例如,c = make(chan int, 1))那么程序将无法保证打印"你好,世界" - 它可能会打印空字符串,崩溃或执行其他操作。这是对的吗?

3 个答案:

答案 0 :(得分:11)

虽然埃文是对的,但我认为更长的解释可能有用:

Effective Go中所述,以下内容相同并为您提供无缓冲频道

ci := make(chan int)            // unbuffered channel of integers
cj := make(chan int, 0)         // unbuffered channel of integers

虽然有任何其他值可以为您提供缓冲频道

ck := make(chan int, 1)         // buffered channel of integers

缓冲频道

使用缓冲通道,Go例程可以在通道(ck <- 42)中放置一个值,然后继续执行下一条指令,而不必等待某人从通道读取。除非通道缓冲区已满,否则这是真的。

如果一个频道已满,Go例程将等待另一个Go例程从该频道读取,然后才能在其中放置自己的值。

无缓冲频道

无缓冲的频道无法存储任何数据。因此,为了使值通过无缓冲通道传递,发送Go例程将阻塞,直到接收Go例程收到该值。

因此,缓冲和无缓冲通道之间肯定存在差异。在内存模型案例中:

package main

var c = make(chan int)
var a string

func f() {
    a = "hello, world"
    <-c
}

func main() {
    go f()
    c <- 0
    print(a)
}

如果你有一个缓冲的频道var c = make(chan int, 1)main() Go例程只会在缓冲区中放置一个值,然后继续使用print(a),可能在f()之前Go例程有时间将a设置为"hello, world"

但是在当前代码中,主要的Go例程将在c <- 0处阻止,等待f()在继续打印之前接收该值,然后我们肯定知道a已设置为"hello, world"

答案 1 :(得分:4)

make(chan int)生成一个无缓冲的通道,make(chan int, 1)生成一个缓冲区为1的通道。

有关差异的解释,请参阅http://golang.org/doc/effective_go.html#channels

答案 2 :(得分:1)

第一个创建一个无缓冲的通道,而第二个创建一个缓冲的通道。

尝试在频道上发送值时,您可以看到区别:

c <- 1

在无缓冲通道的情况下,此语句将阻塞,直到通道上发生相应的接收操作(即<-c)。在缓冲通道的情况下,如果有空间将值存储在通道的缓冲区中,则发送可以完成而不会阻塞。

在大多数情况下,无缓冲的通道是合适的,并且具有以下优点:由于它们的阻塞性质,它们可以快速显示任何并发问题。在某些情况下,缓冲区有意义。

就Go内存模型而言,相同的&#34;发生在&#34;缓冲和非缓冲通道的关系都是正确的。虽然发送操作不会阻止具有缓冲通道的相应接收,但仍然保证在接收之后运行的代码在&#34;之后发生。在发送之前运行的代码。