这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天,记录一下 Go 语言中 channel 的使用方法。
作用
Channel 是 goroutine 之间的一种通信机制,每个 channel 都有一个特定的类型,只能接收或发送该类型的数据。
创建
同 map 和 slice 一样,channel 需要通过 make 关键字来创建。下面的代码创建了一个无缓冲区的、可以接收和发送 int 类型数据的 channel。
// make(chan 元素类型, [缓冲区大小])
ch := make(chan int)
分类
根据有无缓冲区,可以分为无缓冲区 channel 和有缓冲区 channel。
在创建有缓冲区 channel 时,需要额外指定一个参数表示“缓冲区大小”。
ch1 := make(chan string) // 无缓冲区
ch2 := make(chan string, 3) // 有缓冲区,缓冲区大小为3
根据数据传输方向,可以分为只能接收数据的 channel、只能发送数据的 channel 和双向 channel。
chan int // 可以接受和发送 int 类型数据
chan<- string // 只能(向 channel)发送 string 类型数据
<-chan float64 // 只能(从 channel)接收 float64 类型数据
数据传输
发送和接收数据的写法如下。
ch := make(chan int, 1)
ch <- 123 // 向 channel 中发送数据
i := <- ch // 从 channel 中接收数据
发送
对于无缓冲 channel 来说,当向其中发送数据时,如果此时没有接收者,则会一直阻塞,直到接收者到来,因此无缓冲 channel 也被称作“同步 channel”。
对于有缓冲 channel 来说,当向其中发送数据时,会先写入缓冲区,如果缓冲区满了则会一直阻塞,直到缓冲区有空位,因此有缓冲 channel 也被称作”异步 channel“。缓冲区可以看作是一个先入先出(FIFO)队列。
特别的,向一个被关闭的 channel 中发送数据会导致 panic,向 nil channel 中发送数据会一直阻塞。
接收
从 channel 中接收数据会一直阻塞,直到有数据可以接收。
特别的,从一个被关闭的 channel 中接收数据不会阻塞,而是立即返回,接收完已发送的数据后会返回对应类型的零值。