源码地址:https://github.com/golang/go/blob/master/src/runtime/chan.go
type hchan struct {qcount uint // total data in the queuedataqsiz uint // size of the circular queuebuf unsafe.Pointer // points to an array of dataqsiz elementselemsize uint16closed uint32elemtype *_type // element typesendx uint // send indexrecvx uint // receive indexrecvq waitq // list of recv waiterssendq waitq // list of send waiters// lock protects all fields in hchan, as well as several// fields in sudogs blocked on this channel.//// Do not change another G's status while holding this lock// (in particular, do not ready a G), as this can deadlock// with stack shrinking.lock mutex}
qcount uint // 队列中的当前数据的个数
- dataqsiz uint // 环形队列长度,即可以存放的元素个数
- buf unsafe.Pointer // 存放数据的环形数组
- elemsize uint16 // 每个元素的大小
- closed uint32 // 表示 channel 是否关闭的标识位
- elemtype *_type // 队列中元素类型
- sendx uint // 当前发送元素的索引,指示元素写入时存放到队列中的位置
- recvx uint // 当前接受元素的索引,指示元素从队列的该位置读出
- recvq waitq // list of recv waiters 接收等待队列;由 recv 行为(也就是 <-ch)阻塞在 channel 上的 goroutine 队列
- sendq waitq // list of send waiters 发送等待队列;由 send 行为 (也就是 ch<-) 阻塞在 channel 上的 goroutine 队列
- lock mutex lock保护hchan中的所有字段,以及此通道上阻塞的sudoG中的几个字段。
waitq
发送及接收队列的结构体 等待队列的链表实现
type waitq struct {first *sudoglast *sudog}
对 G 的封装
type sudog struct {// The following fields are protected by the hchan.lock of the// channel this sudog is blocking on. shrinkstack depends on// this for sudogs involved in channel ops.g *gselectdone *uint32 // CAS to 1 to win select race (may point to stack)next *sudogprev *sudogelem unsafe.Pointer // data element (may point to stack)// The following fields are never accessed concurrently.// For channels, waitlink is only accessed by g.// For semaphores, all fields (including the ones above)// are only accessed when holding a semaRoot lock.acquiretime int64releasetime int64ticket uint32parent *sudog // semaRoot binary treewaitlink *sudog // g.waiting list or semaRootwaittail *sudog // semaRootc *hchan // channel}
参考
https://www.cyhone.com/articles/analysis-of-golang-channel/
https://github.com/zboya/golang_runtime_reading/blob/master/src/runtime/chan.go
