写在前面
在面试过程中经常会被问到有没有阅读过go源码,前面写了一篇文章go slice扩容是怎么计算大小的 专门针对这个问题的,学了这篇文章你就可以跟面试官说阅读过go源码,并且将他引导到go slice扩容的地方。
go slice的扩容的源码是代码量最少、逻辑最简单的部分源码,入手快,防止面试尴尬。如果面试官继续问:还阅读过其他源码吗?你该怎么回答呢?今天就带大家阅读难度系数很低的go channel源码。(慢慢递进,后面会有map,sync,time相关的源码阅读)
channel源码怎么读
当面试官问go channel源码的时候他在问什么?其实他是在问channel的结构定义。channel没有扩容,接收、发送数据逻辑也都很简单,跟源码没有关系,都是基础知识,去学一下就行。看完这两篇文章就基础知识就差不多了深入理解 go chan和go chan 设计与实现
源码
type hchan struct {
qcount uint // 缓冲区(环形队列)元素个数
dataqsiz uint // 缓冲区的大小(最多可容纳的元素个数)
buf unsafe.Pointer // 指向缓冲区入口的指针(从 buf 开始 qcount * elemsize 大小的内存就是缓冲区所用的内存)
elemsize uint16 // chan 对应类型元素的大小(主要用以计算第 i 个元素的内存地址)
closed uint32 // chan 是否已经关闭(0-未关闭,1-已关闭)
elemtype *_type // chan 的元素类型
sendx uint // chan 发送操作处理到的位置
recvx uint // chan 接收操作处理到的位置
recvq waitq // 等待接收数据的协程队列(双向链表)
sendq waitq // 等待发送数据的协程队列(双向链表)
// 锁
lock mutex
}
hchan有11个属性,记住这11个属性就和相关的基础知识,就可以说阅读过go chan源码了。
记忆方法:
- 先记最重要的4个属性
- buf:指向存储数据的环形队列的指针
- recvq:发送队列
- sendq:接收队列
- lock:锁
上面这个很容易记,记住chan里面有3个队列+1个锁就行,三个队列分别是:数据队列、发送队列、接收队列 - 然后记住buf相关的7个熟悉
- qcount:数据队列中元素数量
- dataqsiz:数据队列容量
- elemtype:元素类型
- elemsize:元素大小
- recvx:接收指针
- sendx:发送指针
- closed:是否关闭
如果面试官问有没有阅读过go chan的源代码,就说读过,go chan有11个属性,它的读写都是围绕着这11个属性实现的。
参考
[1] 深入理解 go chan
[2] go chan 设计与实现
[3] go slice扩容是怎么计算大小的
br>