channel类型
这是go里面的核心数据类型,有了它我们可以方便的进行协程间数据通信。其原理来源于csp模型理论,go实现了部分理论。
简单说,csp模型由并发执行的实体(如进程或线程)组成,实体之间通过发消息进行通信,其中channel承担了实体和实体之间发送消息的通道。
在go里面goroutine
就是实体,它里面也有个channel
来完成通信。
// 定义一个函数
func sum(num int, c chan int) {
res := num + 99
// 数据写入通道
c <- res
}
func main() {
// 定义通道
c := make(chan int)
go sum(100,c)
ret := <-c
fmt.Println(ret) // 打印:199
}
这就是一个最简单的主线程main和协程sum之间的通信。
阻塞
上面的代码中
对于发送者:如果没有接收者读取channel,则发送者会一直阻塞。
同样对于接收者:接收操作是阻塞的知道发送者发送数据。
根据上面的特性,就能实现当goroutine执行完成后得到数据。
func main() {
// 定义通道
c := make(chan int)
sum(100,c) // 去掉了go 就没有开启协程
// 就执行不到这里了,程序被阻塞于此
ret := <-c
fmt.Println(ret) // 打印:199
}
这就是一个会阻塞的代码。
带缓冲的channel
c := make(chan int,2)
这就好比创建了一个带有容量=2的channel(好比队列),只有当队列塞满时发送者会阻塞,队列清空时接受着会阻塞。
// 定义一个函数
func sum(num int, c chan int) {
res := num + 99
// 数据写入通道
c <- res
}
func main() {
// 定义通道
c := make(chan int,2)
sum(100,c)
c <- 123
c <- 456
// 通道定义的容量2,但塞进了3条数据,被阻塞了
// 执行不到下面
fmt.Println("end")
}