通道类型
通道(channel)是用来传递数据的一个数据结构 通道可用于两个 goroutine 之间通过传递一个指定类型的值来同步运行和通讯 操作符 <- 用于指定通道的方向,发送或接收;如果未指定方向,则为双向通道
默认情况下,通道是不带 缓冲区 的;发送端发送数据,同时必须有接收端相应的接收数据 带 缓冲区 的通道允许发送端的数据发送和接收端的数据获取处于异步状态,就是说发送端发送的数据可以放到 缓冲区 里面,可以等待接收端获取数据,而不是立刻需要接收端获取数据 不过由于 缓冲区 的大小是有限的,所以还是必须有接收端接收数据的,否则 缓冲区 一满,发送端就无法发送数据了
ps: 如果通道不带 缓冲区,发送方会阻塞直到接收方从通道中获取了数据 如果通道是带 缓冲区 的,发送方会阻塞直到发送的数据被拷贝到 缓冲区 内 如果 缓冲区 已满,发送方会阻塞直到接收方获取到一个值 接收方在有值可以接收之前会一直阻塞
使用 make、chan 关键字,创建通道,make 的第二个参数可以指定 缓存区 大小
ch := make(chan int) // 创建无缓冲通道
ch := make(chan int, 100) // 创建有缓冲通道,缓冲区大小为 100
ch <- v // 把 v 发送到通道 ch
v := <-ch // 从 ch 接收数据,并赋值给 v
无缓冲区通道
func sum(s []int, c chan int) {
sum := 0
for _, v := range s {
sum += v
}
c <- sum // 把 sum 发送到通道 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 // 从通道 c 中接收
fmt.Println(x, y, x+y)
}
有缓冲区通道
func fibonacci(n int, c chan int) {
x, y := 1, 1
for i := 0; i < n; i++ {
c <- x
x, y = y, x+y
}
close(c)
}
func main() {
c := make(chan int, 10)
go fibonacci(cap(c), c)
// range 函数遍历每个从通道接收到的数据,因为 c 在发送完 10 个
// 数据之后就关闭了通道,所以这里我们 range 函数在接收到 10 个数据
// 之后就结束了。如果上面的 c 通道不关闭,那么 range 函数就不
// 会结束,从而在接收第 11 个数据的时候就阻塞了。
for i := range c {
fmt.Println(i)
}
}