go语言中有一句名言:
不要通过共享内存来通信,而应该通过通信来共享内存。
channel实现了协程间的互相通信。
目录
一、channel声明
无缓冲的channel:
c := make(chan int)
等同于:
c := make(chan int,0)
缓冲队列大小为0,元素类型为int。
阻塞发送直到有协程接收数据,阻塞接收直到有协程发送数据。
带缓冲队列的channel:
c := make(chan int,10)
声明了缓冲大小为10的channel。
二、向channel发送数据
c <- 1
向未初始化的channel(也就是nil channel)写数据,会永久阻塞;
向已关闭的channel写数据,运行会panic,panic: send on closed channel;
三、从channel读取数据
1. i, ok := <-c
ok为false时,代表channel已关闭
2. for i := range c(常用)
range读取channel,只有channel关闭后,才会退出循环
3. select监听多个channel
go func() {
loop:
for {
select {
case i, ok := <-ch1:
if !ok {
break loop
}
fmt.Println("channel1读取到数据: ", i)
}
}
fmt.Println("消费完毕")
wg.Done()
}()
读未初始化的channel(也就是nil channel)数据,会永久阻塞;
读已关闭的channel写数据,当channel中有剩余数据时,会读取剩余数据,否则,会读取元素的零值,所以需要判断ok的值,判断当前channel是否关闭,当channel关闭且channel数据读取完毕之后,ok的值为false。
四、关闭channel
close(c) 直接关闭channel
channel不在消费者侧关闭。
channel的关闭策略:
单生产者多消费者:生产者关闭
多生产者多消费者: 生产者调用sync.Once关闭,或者引入第三方的协调者,关闭channel