摘要:今天我们来学习 Go 语言中 channel , 这是 Go 语言中非常重要的一个特性。
基础知识
创建
在使用 channel 之前需要使用 make 来创建一个 channel, 如果在使用之前没有使用 make, 则会造成死锁(原因在后面死锁部分进行说明)
ch := make(chan int) //创建无缓冲的channel ch := make(chan int, N) //创建有缓冲的channel
读写
N := <- ch //读操作 ch <- N //写操作
分类
无缓冲:发送和接收动作是同时发生的,如果没有 goroutine 读取(<- ch),则发送者(ch <- )会一致阻塞
有缓冲:channel 类似一个有容量的队列,当队列满的时候发送者会阻塞,当队列空的时候接收者会阻塞
关闭
channel 不像文件,通常不需要去关闭它们,只有在接收者必须要知道没有更多的数据的时候,才需要发送端去关闭(只有客户端才应该去关闭),比如在 range 循环遍历中。
ch := make(chan int) close(ch) //关闭 channel
关闭需要注意的几点:
1, 重复关闭 channel 会导致 panic 2, 向关闭的 channel 发送数据会导致 panic 3, 从关闭的 channel 读数据不会发生 panic, 读出 channel 中已有的数据之后, 读出的就是 channel 中值类型的默认值
判断一个 channel 是否关闭可以使用 ok-idiom 的方式,这种方式在 map 中比较常用:
//ok-idiom 方式 val, ok := <- ch if ok == false { fmt.println("closed") }else { fmt.println("not closed") }
典型用法
goroutine 通信
func TestChannel() { ch := make(chan int) go func() { ch <- 1 }() fmt.Println(<- ch) }