转到教程:频道,缓冲频道教程

时间:2018-04-14 14:26:53

标签: go

我正在浏览Go的官方教程,很难理解Channel和Buffered Channels之间的区别。指南的链接是https://tour.golang.org/concurrency/2https://tour.golang.org/concurrency/3

在频道教程中,频道c首先接收[7,2,8]的总和,即17,然后接收[-9,4,0]的总和,即-5。当从c读取时,它首先以LIFO顺序输出-5到x然后输出17到y:

package main

import "fmt"

func sum(s []int, c chan int) {
    sum := 0
    for _, v := range s {
        sum += v
    }
    c <- sum // send sum to c
}

func main() {
    s := []int{7, 2, 8, -9, 4, 0}

    c := make(chan int)
    go sum(s[:len(s)/2], c)
    go sum(s[len(s)/2:], c)
    x, y := <-c, <-c // receive from c

    fmt.Println(x, y, x+y)
}

(以上输出为-5 17 12)

在Buffered Channel教程中,输出为1 2,按FIFO顺序:

func main() {
    ch := make(chan int, 2)
    ch <- 1
    ch <- 2
    fmt.Println(<-ch)
    fmt.Println(<-ch)
}

为什么他们不同?

1 个答案:

答案 0 :(得分:1)

第一个无缓冲通道示例中的chnnael c未充当LIFO。

实际上这是因为go routines而发生的。 go routines同时执行。

如果您调整代码进行调试,请在发送到频道之前添加一行额外的行以打印总和。

package main

import "fmt"

func sum(s []int, c chan int) {
    sum := 0
    for _, v := range s {
        sum += v
    }
    fmt.Println("slice:", s)
    fmt.Println(sum)
    c <- sum         // send sum to c
}

func main() {
    s := []int{7, 2, 8, -9, 4, 0}

    c := make(chan int)
    go sum(s[:2], c)
    go sum(s[2:4], c)
    go sum(s[4:6], c)
    x, y, z := <-c, <-c, <-c // receive from c
    fmt.Println(x, y, z, x+y+z)
}

输出结果为:

slice: [4 0]
4
slice: [7 2]
9
slice: [8 -9]
-1
4 9 -1 12

因此,您可以看到x收到通过频道发送的第一个号码。

此外,无缓冲通道直接将数据发送给接收器。

如果您想了解go中频道的架构,可以观看this talk of gophercon-2017。我觉得这个讲话很有帮助。