我正在浏览Go的官方教程,很难理解Channel和Buffered Channels之间的区别。指南的链接是https://tour.golang.org/concurrency/2和https://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)
}
为什么他们不同?
答案 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
。我觉得这个讲话很有帮助。