Go语言中的无缓冲通道和有缓冲通道(附带实例)
在 Go 语言中,无缓冲的通道是指在接收数据前没有能力保存任何值的通道,有缓冲的通道是指在接收数据前能够存储一个或多个值的通道。
也就是说,对于无缓冲的通道,执行发送和接收数据的操作是同步的,其中的任意一个操作都无法离开另一个操作单独存在。因此,无缓冲的通道又称同步通道。
下例演示无缓冲通道的使用方法。
【实例】定义表示阅读的 read() 函数,该函数包含两个参数,分别是表示图书名称的 webName 和表示通道名称的 chel。在 main() 函数中,创建通道 chel,执行并发程序,接收通道传输的数据,但接收到的数据将被忽略。在控制台中打印“我正在浏览C语言中文网”。代码如下:
可以把有缓冲的通道看作是一个元素队列,使用有缓冲的通道执行发送数据的操作就是在元素队列的尾部插入元素,而接收数据的操作则是从元素队列的头部移除一个元素。
如果有缓冲的通道存储数据的数量达到上限,那么执行发送数据操作的协程将被持续阻塞,直到执行接收数据操作的协程接收有缓冲的通道传输的数据。
如果有缓冲的通道存储数据的数量为零,那么执行接收数据操作的协程将被持续阻塞,直到执行发送数据操作的协程使用有缓冲的通道发送数据。
在使用有缓冲的通道完成发送与接收数据的操作时,不强制要求执行发送数据操作的协程和执行接收数据操作的协程同时准备就绪。
下例演示有缓冲通道的使用方法。
【实例】打印有缓冲的通道内部存储数据的数量。首先,创建一个有缓冲的通道 chel,该通道内部存储数据的数量上限为 6。然后,打印该通道内部存储数据的数量。接着,使用有缓冲的通道发送数据,数据依次为 0、1、2 和 3,最后打印该通道内部存储数据的数量。代码如下:
Go语言无缓冲通道
为了能够让无缓冲的通道完成发送、接收数据的操作,执行发送数据操作的协程和执行接收数据操作的协程需要同时准备就绪。也就是说,对于无缓冲的通道,执行发送和接收数据的操作是同步的,其中的任意一个操作都无法离开另一个操作单独存在。因此,无缓冲的通道又称同步通道。
下例演示无缓冲通道的使用方法。
【实例】定义表示阅读的 read() 函数,该函数包含两个参数,分别是表示图书名称的 webName 和表示通道名称的 chel。在 main() 函数中,创建通道 chel,执行并发程序,接收通道传输的数据,但接收到的数据将被忽略。在控制台中打印“我正在浏览C语言中文网”。代码如下:
package main import ( "fmt" ) // 表示“阅读”的函数,参数有两个: // webName:图书的名称 // chel:通道的名称 func read(webName string, chel chan bool) { fmt.Println("我正在浏览" + webName) chel <- true // 使用通道 chel 发送数据 } func main() { chel := make(chan bool) // 创建通道 chel // 执行并发程序 go read("C语言中文网", chel) <-chel // 通道传输的数据被接收,但是接收到的数据将被忽略 }运行结果如下:
我正在浏览C语言中文网
Go语言有缓冲通道
在 Go 语言中,创建有缓冲的通道的语法格式如下:name := make(chan type, num)参数说明如下:
- name:通道的名称;
- make:make() 函数,用于创建通道;
- chan:Go 语言关键字,通道类型;
- type:在通道内部传输的数据的类型;
- num:通道内部存储的数据的数量上限。
可以把有缓冲的通道看作是一个元素队列,使用有缓冲的通道执行发送数据的操作就是在元素队列的尾部插入元素,而接收数据的操作则是从元素队列的头部移除一个元素。
如果有缓冲的通道存储数据的数量达到上限,那么执行发送数据操作的协程将被持续阻塞,直到执行接收数据操作的协程接收有缓冲的通道传输的数据。
如果有缓冲的通道存储数据的数量为零,那么执行接收数据操作的协程将被持续阻塞,直到执行发送数据操作的协程使用有缓冲的通道发送数据。
在使用有缓冲的通道完成发送与接收数据的操作时,不强制要求执行发送数据操作的协程和执行接收数据操作的协程同时准备就绪。
下例演示有缓冲通道的使用方法。
【实例】打印有缓冲的通道内部存储数据的数量。首先,创建一个有缓冲的通道 chel,该通道内部存储数据的数量上限为 6。然后,打印该通道内部存储数据的数量。接着,使用有缓冲的通道发送数据,数据依次为 0、1、2 和 3,最后打印该通道内部存储数据的数量。代码如下:
package main import "fmt" func main() { chel := make(chan int, 6) // 创建有缓冲的通道chel // 打印有缓冲的通道内部存储数据的数量 fmt.Println("有缓冲的通道内部存储数据的数量:", len(chel)) // 使用有缓冲的通道发送数据 chel <- 0 chel <- 1 chel <- 2 chel <- 3 // 再次打印有缓冲的通道内部存储数据的数量 fmt.Println("有缓冲的通道内部存储数据的数量:", len(chel)) }运行结果如下:
有缓冲的通道内部存储数据的数量:0
有缓冲的通道内部存储数据的数量:4