源码地址:https://github.com/golang/go/blob/master/src/runtime/chan.go

  1. type hchan struct {
  2. qcount uint // total data in the queue
  3. dataqsiz uint // size of the circular queue
  4. buf unsafe.Pointer // points to an array of dataqsiz elements
  5. elemsize uint16
  6. closed uint32
  7. elemtype *_type // element type
  8. sendx uint // send index
  9. recvx uint // receive index
  10. recvq waitq // list of recv waiters
  11. sendq waitq // list of send waiters
  12. // lock protects all fields in hchan, as well as several
  13. // fields in sudogs blocked on this channel.
  14. //
  15. // Do not change another G's status while holding this lock
  16. // (in particular, do not ready a G), as this can deadlock
  17. // with stack shrinking.
  18. lock mutex
  19. }

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

发送及接收队列的结构体 等待队列的链表实现

  1. type waitq struct {
  2. first *sudog
  3. last *sudog
  4. }

对 G 的封装

  1. type sudog struct {
  2. // The following fields are protected by the hchan.lock of the
  3. // channel this sudog is blocking on. shrinkstack depends on
  4. // this for sudogs involved in channel ops.
  5. g *g
  6. selectdone *uint32 // CAS to 1 to win select race (may point to stack)
  7. next *sudog
  8. prev *sudog
  9. elem unsafe.Pointer // data element (may point to stack)
  10. // The following fields are never accessed concurrently.
  11. // For channels, waitlink is only accessed by g.
  12. // For semaphores, all fields (including the ones above)
  13. // are only accessed when holding a semaRoot lock.
  14. acquiretime int64
  15. releasetime int64
  16. ticket uint32
  17. parent *sudog // semaRoot binary tree
  18. waitlink *sudog // g.waiting list or semaRoot
  19. waittail *sudog // semaRoot
  20. c *hchan // channel
  21. }

参考

https://www.cyhone.com/articles/analysis-of-golang-channel/
https://github.com/zboya/golang_runtime_reading/blob/master/src/runtime/chan.go