目录

Channel

性质

  • 向已经关闭的通道发送数据,会引发panic

  • close已经关闭的channel或值为nilchannel,会引发panic

  • 从已关闭接收数据,返回已缓冲数据或零值

  • 无论收发,nil通道都会阻塞

type hchan struct {
    buf      unsafe.Pointer // 环形队列指针
    elemtype *_type         // 元素类型
    elemsize uint16         // 每个元素的大小
    dataqsiz uint           // 环形队列长度
    qcount   uint           // 剩余位置数
    sendx    uint           // 队列写入位置
    recvx    uint           // 队列读出位置
    recvq    waitq          // 等待读消息的 goroutine 队列
    sendq    waitq          // 等待写消息的 goroutine 队列
    closed   uint32         // 标识关闭状态
    lock mutex              // 互斥锁,chan不允许并发读写
}
环形队列示意图

挂载的Goroutine示意图

环形队列的剩余存储空间大小,决定了Goroutine读写Channel时,是否发生堵塞。

当剩余空间发生变化时,将会唤醒相应的阻塞状态的Goroutine

由于Channel内部带了锁机制,所以它同时仅允许被一个goroutine读写。

向Channel中写入数据示意图

从Channel中读取数据

关闭Channel

以下两种情况,会报panic

  • 关闭值为nil的channel

  • 关闭已经被关闭的channel

关闭channel时:

  • 会把recvq中的G全部唤醒,本该写入G的数据位置为nil

  • sendq中的G全部会panic,即向已经关闭的channel写数据会panic

Select

type scase struct {
    c           *hchan                         // 当前case语句所操作的channel指针
    kind        uint16                         // 类型,分为读channel、写channel和default
    elem        unsafe.Pointer // 读出/写入channel的数据存放地址(缓冲区地址)
}