Go语言带缓冲channel教程
中的 有两种类型,分别为: 和 带缓冲 channel。
无缓冲的通道是指在接收前没有能力保存任何值的通道。这种类型的通道要求发送 和接收 goroutine 同时准备好,才能完成发送和接收操作。
带缓冲的通道是一种在被接收前能存储一个或者多个值的通道。这种类型的通道并不强制要求 goroutine 之间必须同时完成发送和接收。
带通道会阻塞发送和接收动作的条件也会不同。只有在通道中没有要接收的值时,接收动作才会阻塞。只有在通道没有可用缓冲区容纳被发送的值时,发送动作才会阻塞。
Go语言无缓冲通道和带缓冲通道区别
无缓冲的通道保证进行发送和接收的 goroutine 会在同一时间进行数据交换,而有缓冲的通道没有这种保证。
在无缓冲通道的基础上,为通道增加一个有限大小的存储空间形成带缓冲通道。带缓冲通道在发送时无需等待接收方接收即可完成发送过程,并且不会发生阻塞,只有当存储空间满时才会发生阻塞。同理,如果缓冲通道中有数据,接收时将不会发生阻塞,直到通道中没有数据可读时,通道将会再度阻塞。
无缓冲通道保证收发过程同步。而无缓冲是异步的收发过程,因此效率可以有明显的提升。
带缓冲channel创建
语法
c1:= make(chan TYPE, bufferSize)
参数
参数 | 描述 |
---|---|
c1 | channel 变量名。 |
chan | 创建 channel 使用的关键字。 |
TYPE | channel 的类型。 |
bufferSize | channel 的缓冲区大小。 |
说明
我们创建了一个带缓冲的 channel c1,其类型为 chan TYPE,缓冲区大小为 bufferSize。
案例
带缓冲channel读写数据
使用带缓冲 channel 读写数据
package main import ( "fmt" "time" ) //使用带缓冲 channel 发送数据 func writeRoutine(intChan chan int) { for i := 0; i < 3; i++ { intChan <- i time.Sleep(time.Duration(2) * time.Second) fmt.Println("Send", i) } //关闭 channel close(intChan) } // 从带缓冲 channel 读取数据 func readRoutine(intChan chan int) { for val := range intChan{ fmt.Println("Receive =", val) time.Sleep(time.Duration(10) * time.Second) } return } func main() { fmt.Println("嗨客网(www.haicoder.net)") // 创建带缓冲 channel c := make(chan int, 3) go writeRoutine(c) readRoutine(c) }
程序运行后,控制台输出如下:
首先,我们使用 创建了一个带缓冲的 channel,其缓冲区大小为 3,接着,分别创建了一个负责写入数据的协程 writeRoutine 和一个负责读取数据的协程 readRoutine。
在 writeRoutine 协程里,我们使用 发送三次数据,每次发送数据后,都使用 sleep 等待两秒,数据全部发送完毕,使用 关闭 channel。
在 readRoutine 函数里,使用 接受数据,每次接受完数据后,都等待 10 秒钟。接受数据的时长明显长于发送数据的时长。
因为,发送数据的时间间隔明显小于接受数据的时间间隔,如果我们使用的是无缓冲的 channel,那么此时接受和发送是同步的,必须是接受完才能发送下一个。
但,我们这里创建的是无缓冲的 channel,因此,发送数据端不必等待数据被接受,就可以继续下一次发送,除非缓冲区满,才会阻塞,因此,我们看到的收发数据的效果是异步的。
Go语言带缓冲channel总结
带缓冲的通道是一种在被接收前能存储一个或者多个值的通道。这种类型的通道并不强制要求 goroutine 之间必须同时完成发送和接收。Go 语言带缓冲 channel 创建:
c1:= make(chan int, bufferSize)