在上一篇文章 《Go 并发:Channel 通道》中,我们讨论了通道的一些基本特性,需要指出的是,之前讨论的通道都是不带缓冲的通道,也就是说从通道接收数据和往通道发送数据都会阻塞,直到有其他 goroutine 往通道发送数据或从通道接收数据。
在这篇文章中,我们继续讨论带缓冲的通道的使用。
带缓冲的通道
可以创建带缓冲的通道。往通道发送数据时,只有当缓冲满时才会阻塞。同理,从通道接收数据时,只有当缓冲为空时才会阻塞。
可以使用 make 函数来创建带缓冲的通道:
ch := make(chan type, capacity)
其中,capacity 大于 0 时表示通道带缓冲。capacity 默认为 0 ,所以如果省略 capacity 参数则创建不带缓冲的通道。
例子一
package main
import "fmt"
func main() {
ch := make(chan string, 2)
ch <- "lee"
ch <- "leo"
fmt.Println(<-ch)
fmt.Println(<-ch)
}
在上面的程序中,ch := make(chan string, 2) 创建了一个带缓冲的字符串类型通道,缓冲大小为 2,因此,可以连续往该通道发送 2 个字符串数据也不会阻塞。
接下来,往通道发送 2 个字符串,然后从通道读取这两个字符串,并打印出来:
lee
leo
例子二
接着我们来实现一个更复杂点的例子。
package main
import (
"fmt"
"time"
)
func write(ch chan int) {
for i := 0; i < 5; i++ {
ch <- i
fmt.Println("wrote ", i, "to ch")
}
close(ch)
}
func main() {
ch := make(chan int, 2)
go write(ch)
time.Sleep(2 * time.Second)
for v := range ch {
fmt.Println("read value", v, "from ch")
time.Sleep(2 * time.Second)
}
}
在上面的程序中,创建了一个带缓冲的整形通道,缓冲大小为 2 。然后在 main goroutine 中启动了 write goroutine。在 write goroutine 中,循环往通道发送数字 0 - 4。由于通道缓冲大小为 2,故发送数字 0 和 1 后,write goroutine 将阻塞。write goroutine 阻塞前打印:
wrote 0 to ch
wrote 1 to ch
write goroutine 打印上面两行输出后,将会阻塞。main goroutine 在睡眠 2 秒后,从通道 ch 接收数字 0。这时,write goroutine 可以继续往通道发送数字 2:
read value 0 from ch
wrote 2 to ch
接下来,write goroutine 将剩余数字发送,main goroutine 将剩余数字打印出来:

最低0.47元/天 解锁文章
557

被折叠的 条评论
为什么被折叠?



