dotGo 2019 技术总结
(本文亦发布于Human Coders博客的法语版本)
大约两周前,我有幸参加了第五届欧洲Go大会dotGo 2019。与我过去参加的通常在人迹罕至的酒店或会议中心举办的技术会议不同,dotGo团队全力以赴,成功将巴黎著名的Blanche街剧院作为会议场地。毫无疑问,包括Heetch、Microsoft、Datadog、Sourcegraph和GitHub在内的赞助商提供了帮助。
Go语言传奇人物Dave Cheney担任主持人。尽管会议时间短暂(一天会议加一天研讨会),但议程排满了技术演讲。以下是我的收获。这里我不会过于深入细节;只是想让你对演讲内容有个大致了解,完整演讲视频很快将在dotconferences.com上发布。
(对Go语言感兴趣的人可能有兴趣知道,我通过Human Coders为Go初学者提供培训。)
第一场会议
Daniel Martí:更可靠的微基准测试
Daniel Martí以一场相当技术性的演讲拉开了会议序幕。虽然Go命令行界面允许程序员对性能关键代码部分运行微基准测试,但由于差异过大,结果可能不确定。简单来说,由于各种环境因素(如CPU活动),微基准测试在一次运行中可能表现良好,但在后续运行中却令人失望。Daniel展示了一些新技术来减少噪声,并从微基准测试中获得更明确的结果。
Kat Zién:领域驱动设计与Go
Kat Zién随后就一个贴近我领域驱动设计者内心的主题进行了演讲:六边形架构。这个术语由Alistair Cockburn创造,但基本思想可以追溯到更早时期,并以不同名称被不断重新发现,如“洋葱架构”。六边形架构通过清晰地将业务领域的实现与支持它的技术组件(如数据库)分离来构建系统。这种方法承诺带来更易理解和维护的系统。
Kat的演讲是对六边形架构的良好介绍,但我希望她能展示如何将其原则具体应用于Go程序(可以查看Marcus Olsson关于此主题的演讲)。然而,演讲必须保持简短,我可以原谅Kat没有深入探讨细节。我一定会关注她未来的演讲。
Ignat Korchagin:将Go作为脚本语言
Ignat Korchagin随后阐述了将Go用作脚本语言需要克服的障碍。特别是,Go的语法与标准shebang语法不兼容,这使我们的生活更加困难。Ignat展示了一些变通方法,但还没有一个令我满意。目前我还会坚持使用Python或shell脚本。
Michael McLoughlin:更接近硬件
Michael McLoughlin随后讨论了在Go中编写汇编语言的机制,重点关注amd64架构。当性能至关重要时,Go有时可能不够用,你必须诉诸编写汇编代码;实际上,几个标准库例程不是用Go编写的,而是用汇编编写的。然而,编写原始汇编代码是一项危险的实践(没有类型检查器指导你走向正确性),错误可能带来严重后果(想象加密例程中的错误)。
Michael对这个问题的答案是avo,它允许你编写Go程序来生成汇编代码。好处很明显:提供给avo的Go源代码比手工编写的汇编代码更紧凑、更易于测试、理解和维护,而生成的汇编代码性能相同。Michael通过展示SHA-1实现来说明他方法的好处;令人印象深刻!
第二场会议
闪电演讲
随后观众欣赏了Olivier Wulveryck、Roberto Clapis、Natalie Pistunovich、Valentin Deleplace和Joan López de la Franca Beltran的一系列闪电演讲。对我来说,Valentin Deleplace的信号量双重实现是亮点。你可以将信号量想象成一个游泳池,顾客在进入游泳池前必须每人戴一顶泳帽,而只有固定数量的泳帽可用。或者,你可以将信号量想象成一个游泳池,顾客在进入游泳池前必须锁好随身物品,而储物柜数量有限。
Dave Cheney:常量与变量
常规长度的演讲以Dave Cheney的演讲恢复。暂时脱离主持人角色,Dave选择重新审视他2016年的一篇博客文章。Go包通常使用errors.New函数定义一些哨兵错误值。例如,io和rsa包分别定义了名为EOF和ErrVerification的结构体值,客户端随后可以在相等性测试中使用这些值来检测代码是否偏离了正常路径。
在理想世界中,这样的哨兵错误值本当是常量,但由于一些语言特性,这些值必须定义为变量(使用var),因此可以被定义它们的包的客户端覆盖。你可以想象这在正确性和安全性方面的后果。
Dave随后分享了他的变通方法:首先,定义一个底层类型为字符串的自定义错误类型,为其配备一个简单地返回字符串值的Error方法,并用它定义你的哨兵错误值。然后,后者可以定义为const而不是var,一切就都好了。这是一个有趣的方法,你可以在代码中自由尝试,尽管这种习惯用法不太可能在标准库中普及。
Jean de Klerk:Go模块与Git仓库
Jean de Klerk讨论了拥有多模块仓库的复杂性。不久前,Go中的依赖管理还有很多不足之处。当Go 1.11添加了一个真正的模块系统(源自vgo项目)时,一切都(向好的方向)改变了。模块系统仍处于起步阶段,预计将在1.13版本达到通用可用状态。
推荐的方法是在每个Git仓库中有一个Go模块。然而,在某些情况下,你可能希望在同一仓库中跟踪多个模块,尤其是在Google工作时,该公司似乎坚定地支持单体仓库。这里有陷阱!我会让你观看Jean的演讲了解细节,但我的经验法则是:一个模块,一个仓库。
第三场会议
Johann Brandhorst:从Go到WebAssembly
Johann Brandhorst为我们准备了另一场现场编码会议,这次是关于使用Go编写WebAssembly。由于我自己还没有深入研究WebAssembly,Johann的一些演讲内容超出了我的理解范围,但如果观众的反应有任何指示的话,好事情正在向我们走来。
Bryan Boreham:垃圾回收器调优
Bryan Boreham就如何调优Go的垃圾回收器进行了演讲。JVM的垃圾回收器提供了众多选项,并且 notoriously 难以调优;有整本书专门讨论这种黑暗艺术。对Gopher来说,生活相对简单:只有一个名为GOGC的选项可用于调优Go垃圾回收器!然而,Bryan承认,拥有设置堆最小和最大大小的选项会很有用……
顺便说一句,对于内存需求适中且执行时间保证较短的程序,Bryan告诉我们,通过完全禁用垃圾回收器(GOGC=off)可以获得性能提升。一个很酷的技巧!
Ellen Körbes:不,这不是性玩具……
Ellen Körbes(这一点很重要,他们认同为非二元性别)进行了一场大胆的现场编码演讲,关于如何使用基于Go的3D建模工具设计自己的阴道扩张器——如果需要的话,可以查一下这个词。彻头彻尾的极客,他们甚至通过在外端添加一个Gopher头来增强原始设计。很好的点缀!
最后一场会议
James Bowes:reflect和unsafe的危险
James Bowes让我们思考普通人是否应该使用 notorious 的reflect和unsafe包。reflect的使用在标准库中无处不在:每当你看到空接口(interface{})或结构体标签时,reflect很可能在幕后施展魔法。至于unsafe,它在绕过类型系统对良好性能至关重要的地方使用。
然而,这两个包在被新手使用时可能很危险——包括我自己。James的告诫很明确:作为经验法则,远离unsafe包,并抵制使用reflect的诱惑(例如用于运行时依赖注入)。
Jess Frazelle:生活在RISC-V中
Jess Frazelle是Go社区的一颗明亮之星。她有一种令人耳目一新的方式,每隔一句话就爆粗口,这让观众保持警觉。她带我们快速浏览了x86指令集的动物园。一个突出的x86指令集架构是RISC-V,Jess谈到了她在为该架构添加Go支持方面的工作。
Marcel van Lohuizen:错误包装成为主流
作为会议的最后一场演讲,Marcel van Lohuizen调侃了Go错误处理机制即将到来的改进。包装错误,即在错误本身内部引用错误原因的做法,是Go标准库errors包中明显缺失的有用功能。为了填补这一空白,社区分裂成许多不同的错误包装方法,所有这些方法都以略微不同的方式互不兼容。迫切需要围绕错误应如何包装进行标准化。
Marcel的演讲描述了errors API将如何在Go 1.13中扩展,以适应规范的错误包装方式。计划的更改还开启了错误消息本地化的可能性,为那些宁愿用母语阅读错误消息的程序员带来好处。
新的API已经在实验包golang.org/x/exp/errors中可用。很棒的东西!
尾声
在红磨坊隔壁的某家酒吧(名字我忘了)喝了几品脱酒后,是时候睡一觉了。
网络上已经出现了其他报道——包括这篇(法语)——我邀请你阅读它们,以获取关于会议的不同视角。
再次感谢Human Coders,他们慷慨地给了我一张会议门票。dotGo 2020已经宣布,将于明年三月在同一场地举行。如果像今年的版本一样,我会尽力参加,你也应该如此。