- In short, the channel maintains a receiving and sending queue with pointers , which contains mutex locks to ensure concurrency security, data type, number of elements, element size, and channel status
- Then read and write operations, first check whether the queue can be taken out, then check the buffer, and finally put it into the receive/send queue
- Closing is to wake up all goroutines and set their flags to 1, which means they are closed, and if someone visits them in the future, they will be nil
Structure source code
type hchan struct {
qcount uint // 当前队列中元素的数量
dataqsiz uint // 缓冲区大小,即可以缓存的元素数量
buf unsafe.Pointer // 指向队列的缓冲区
elemsize uint16 // 每个元素的大小
closed uint32 // channel 是否已关闭的标志
elemtype *_type // channel 中元素的类型
sendx uint // 下一次发送元素的位置
recvx uint // 下一次接收元素的位置
recvq waitq // 等待接收的 goroutine 队列
sendq waitq // 等待发送的 goroutine 队列
lock mutex // 用于保护 channel 的互斥锁
}
send data
When a goroutine wants to send data to the channel, it executes chansend
the function.
- This function will first lock the channel , and then determine whether there are goroutines waiting to receive
- If there is , send the data to it directly; otherwise, if the buffer is not full, put the data into the buffer and add one to the number of elements in the queue;
- If the queue is full , add the current goroutine to the queue of goroutines waiting to send , and block it, waiting for other goroutines to receive data.
accept data
When a goroutine wants to receive data from a channel, it executes the function src/runtime/chan.go
in chanrecv
.
- This function will also lock the channel , and then judge whether there is a goroutine waiting to be sent, and if so, receive data directly from it;
- Otherwise, if the number of buffer elements is greater than 0, an element is taken from the buffer and the number of elements in the queue is decremented by one.
- If the buffer is empty, add the current goroutine to the queue of goroutines waiting to receive , and block it, waiting for other goroutines to send data.
close channel
When a goroutine wants to close the channel, it executes the function src/runtime/chan.go
in closechan
.
- This function will lock the channel, and then
closed
set the flag to 1, indicating that the channel has been closed. - Then traverse the queue of goroutines waiting to send and wait to receive, wake them up, and return a special value to indicate that the channel has been closed.