我们都知道,进程间、线程间如果需要沟通合作,那么就需要进行通信。
因为每个执行流都有他自己的上下文,除非特殊情况,不能随便互相干涉,不然计算机就乱了套了。
协程也不例外,Go 提供了管道 Channel 来实现协程间的通信。
上代码:
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) // 使用 make 初始化一个 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)
}
上述代码利用协程并发计算两个求和,并且通过管道传送到了主协程,并打印出来。
Go 的管道也支持缓存:
package main
import "fmt"
func main() {
ch := make(chan int, 2) // 初始化大小为 2 的管道
ch <- 1 // 塞入数据
ch <- 2
fmt.Println(<-ch) // 获取数据
fmt.Println(<-ch)
}
这里有个知识点,当一个协程向管道里塞入超过缓存大小的数据时,该协程会被阻塞(block),直到缓存空间被释放出来。
ok,下一章见~