1、无缓冲通道
Go语言中无缓冲的通道(unbuffered channel)是指在接收前没有能力保存任何值的通道。这种类型的通道要求发送 goroutine 和接收 goroutine 同时准备好,才能完成发送和接收操作。如果两个 goroutine 没有同时准备好,通道会导致先执行发送或接收操作的 goroutine 阻塞等待。
2、带缓冲的通道
Go语言中有缓冲的通道(buffered channel)是一种在被接收前能存储一个或者多个值的通道。这种类型的通道并不强制要求 goroutine 之间必须同时完成发送和接收。通道会阻塞发送和接收动作的条件也会不同。只有在通道中没有要接收的值时,接收动作才会阻塞。只有在通道没有可用缓冲区容纳被发送的值时,发送动作才会阻塞。
有缓冲的通道和无缓冲的通道之间的一个很大的不同:无缓冲的通道保证进行发送和接收的 goroutine 会在同一时间进行数据交换;有缓冲的通道没有这种保证。
在无缓冲通道的基础上,为通道增加一个有限大小的存储空间形成带缓冲通道。带缓冲通道在发送时无需等待接收方接收即可完成发送过程,并且不会发生阻塞,只有当存储空间满时才会发生阻塞。同理,如果缓冲通道中有数据,接收时将不会发生阻塞,直到通道中没有数据可读时,通道将会再度阻塞。
1)创建带缓冲的通道
通道实例 := make(chan 通道类型, 缓冲大小)
- 通道类型:和无缓冲通道用法一致,影响通道发送和接收的数据类型。
- 缓冲大小:决定通道最多可以保存的元素数量。
- 通道实例:被创建出的通道实例。
3、通道的多路复用
Go语言中提供了 select 关键字,可以同时响应多个通道的操作。由 select 开始一个新的选择块,每个选择条件由 case 语句来描述,每个 case 语句都必须是一个面向 channel 的操作,大致结构如下:
select{
case 操作1:
响应操作1
case 操作2:
响应操作2
…
default:
没有操作情况
}
- 操作1、操作2:包含通道收发语句。
- 响应操作1、响应操作2:当操作发生时,会执行对应 case 的响应操作。
- default:当没有任何操作时,默认执行 default 中的语句。
4、关闭通道
使用 close() 来关闭一个通道:close(ch)
关闭的通道依然可以被访问,访问被关闭的通道将会发生一些问题。
被关闭的通道不会被置为 nil。如果尝试对已经关闭的通道进行发送,将会触发宕机。
从已经关闭的通道接收数据或者正在接收数据时,将会接收到通道类型的零值,然后停止阻塞并返回。
示例:
package main import "fmt" func main() { ch := make(chan int, 2) ch<-0 close(ch) for i := 0; i < 2 ; i++ { v, ok := <-ch fmt.Println(v, ok) } }