最近我参加了几次围棋面试.第一个问我How is channel implemented?,然后第二个问我How is goroutine implemented?.你可以猜到,下一个问道How is a Go interface implemented?.
我一直在使用Go六个月,但说实话,我从来没有关心或知道这些Go internals.
我试着通过阅读Go的源代码来学习这些,但却无法真正理解这些精髓.
所以问题是,对于Go中的菜鸟,我如何学习Go internals?
kos*_*tix 11
让我警告你,你可能会错过采访者的真实观点.
(免责声明:我不时对Go程序员进行面试,对于一个要求很高的项目,因此下面的所有内容都是我的个人世界观.不过,我的牛犊共享;-)).
大多数情况下,一个员工确切地知道运行时(或编译器)的这个或那个位是如何实现的 - 这在一定程度上是没有价值的 - 因为这可能会在将来的任何版本中发生变化,部分原因是至少确实存在Go的两个最新实现("gc套件",以及GCC的一部分),他们都可以自由地以任何方式实现特定功能.
一个(明智的)面试官应该真正感兴趣的是你是否理解特定核心特征的"原因".
比如说,当他们要求您解释如何实现某个频道时,他们应该感兴趣的是,频道提供同步并且还可以提供缓冲.所以你可以告诉他们一个通道就像
一个受互斥锁保护的变量 - 对于一个无缓冲通道的情况,或者像一个受互斥锁保护的切片.然后补充一点,使用通道而不是手工制作的涉及互斥锁的解决方案的结果是可以使用select语句轻松组合通道上的操作,同时实现没有通道的匹配功能(并且到那时它们可能我想听听你的意见,sync.Cond但是真的很麻烦且容易出错.
知道渠道的细节并不是完全没有价值 - 比如知道他们的实施努力降低"快乐案例"中同步的价格(目前goroutine访问渠道时没有争用)而且,在"不开心的情况"中没有直接跳入内核睡觉的时候也很聪明,但我认为这些细节并没有任何意义.
这同样适用于goroutines.您应该清楚地了解OS进程与其中运行的线程之间的区别,以及哪个上下文属于一个线程 - 即在线程之间切换时需要保存和恢复的内容.然后是OS线程和goroutine主要是"绿色线程"之间的差异.只知道谁调度操作系统线程和谁安排goroutine,以及为什么后者更快,这是可以的.什么是具有够程的好处(最主要的是网络轮询集成到调度(见本),二是动态栈,第三个是背景低切换开销的大部分时间).
我的建议是阅读@icza提供的列表.
除了你所问的内容之外,我还会列出一个好的候选人应该熟悉的列表 - 从最简单到最难(到grok)的顺序:
切片和切片的机制append.您应该知道数组存在以及它们与切片的不同之处.
如何实现接口.
Go字符串的二元性质(给定s包含一个字符串,通过for i := 0; i < len(s); i++ { c := s[i] }over 迭代其内容之间的区别是什么
for i, c := range s {}).
另外:什么类型的数据字符串可能包含 - 你应该知道在它们中包含任意二进制数据是完全可以的,UTF-8不是必需的.
string和之间的区别[]byte.
如何实现阻塞I/O(对于网络;这是关于集成到运行时的netpoller).
了解处理非网络阻塞I/O和系统调用的差异通常是一个额外的好处.
如何实现调度程序(那些P在Gs上运行M).
最有组织的内部资源链接集合可能是这样的:
除此之外,这些问题的答案不是一次性收集的,而是分散在不同的博客帖子中.
Slice internals:Go Blog:用法和内部
String internals:Go Blog:Go中的字符串,字节,符文和字符
常数内部:Go Blog:常量
反思洞察:Go Blog:反思的法则
接口内部:RSC:Go Data Structures:接口
渠道实施:SO概述:如何实施Go渠道?
通道内部:使用类固醇通道
地图实施:SO概述:Golang地图内部实施 - 如何在地图中搜索密钥?
地图内部:地图内部的宏观视图在Go
这个 GitHub 存储库将有助于了解 go 内部。
您可以在此处获取所有与内部相关的资源。