可汗网络学院编写了50万行Go代码后两点心得


这是他们使用Go语言的经验教训的分享,其中主要比较了Go与Python两者语言的不同使用感受:
早在2019年12月,我首先写了关于可汗学院的项目Goliath的项目,该项目将我们的后端从Python 2整体迁移到用Go编写的服务。当我们开始Goliath时,团队中没有人知道Go,除了我们进行的实验以证明Go比其他选择对我们来说是一个更好的选择。今天,我们所有的后端和全栈工程师都在编写Go,而Goliath的增量交付使我们跨过了一个重要的里程碑:现在有超过500,000条Go生产线正在运行。这似乎是对Go本身进行反思的好时机。
 
工程师喜欢Go
我向工程师询问了有关Go的一些开放式反馈,并且听到了诸如“易于阅读和编写”以及“我更喜欢Go”之类的反馈。
一位工程师在.NET领域花费了多年的时间,并重视异常样式的错误处理,这与Go的错误处理大不相同。如果您不熟悉该主题,则Go错误是从可能具有错误条件的函数返回的值。这位前.NET工程师现在说:“能够调用不会返回错误并确定必须成功的函数真是太好了。”
另一位工程师引用了Go的标准库文档。他喜欢“通过go doc io.Writer可以进行无互联网浏览的功能”。
通常,Go工具是很棒的。编译器速度很快,格式化已成为标准工具链的一部分,有助于消除大多数有关格式化的问题。尽管我仍然在Internet上看到关于Go模块的抱怨,但是它们比Go中以前的软件包管理方法要好得多,因此,就我们的经验而言,它们总体上还不错。我们也很容易找到需要完成的工具和库,例如gqlgen
 
我们需要泛型,否则Go会更加冗长
在大多数情况下,编写没有泛型类型的Go代码是可以的。大多数时候,但是很多时候我们一直在编写内部库代码,或者当我们感觉到无法使用泛型时只能使用slices。

  1. 缺乏泛型是人们对Go最大的抱怨。接受调查的工程师赞赏Go团队花了很多时间来制作适合Go泛型这一事实,我们为这项工作正在向前而感到兴奋。至少从发布Go语言以来至今我们才用了几年的时间。
  2. 在移植Python代码时,一位工程师指出,某些语言结构在Go上编写时花费了更多的精力,但是Go相对较精简的语言功能也使代码更一致,更易于阅读。对于我们系统的一部分,我们需要2.7倍的Go行来处理与Python代码相同的功能,尽管部分原因是由于使用跨服务查询替换了某些函数调用。
  3. 另一位工程师希望能够更好地利用高阶函数,并且所提出的slice软件包在这些方面看起来是不错的补充。最终,我们希望编写更少的代码,而泛型获得的选项将对此有所帮助。

 
性能与并发
相比Python(或Python 2),我们发现Go的性能非常出色。从Python到Go,我们正在尽可能接近1:1比例原样移植运行,而最终仍然以类似于Go的方式结束,而不是像看起来像Python-in-Go的代码。在这个过程中,我们明确地不优先考虑性能的工作,除非有真正的递归功能。
一位工程师指出,某些批量数据更改曾经在Python版本中每小时产生约100个Google Cloud Datastore竞争警告,而在Go版本中几乎每小时都产生零个警告,因为它处理数据的速度更快。我们有一个异常案例,某个课程包含1,000名学生,Python可能需要28秒才能加载,而在Go中只需4秒。
尽管我们从大量的单线程Python进行了直接移植,但是我们确实已经对Go的并发功能进行了一些使用。一位工程师指出,尽管通道Channel是Go的突出功能,但我们使用sync软件包的功能远远超过了通道。看看我们的喜好是否随时间变化会很有趣。
 
总结一下:
  • 是的,Go一般比Python更冗长...
  • 但是我们喜欢它!快速,工具扎实,并且在生产中运行良好

我们的工程师来自不同的编程背景,因此对于Go语言和其他语言,我们当然有多种见解。我们感谢推动其持续发展的团队以及围绕它建立的社区!