为什么我选择放弃 Python,转而使用 Go?

发表时间: 2018-08-20 10:59

近日,Python 被纳入

全国计算机等级考试科目

、编入了小学教材、获得了

2018 年顶级编程语言荣誉

,可以说,Python 要多火就有多火。而本文并非为此火上添油,而是适时地为 Python 浇了一盆凉水,稳步发展才是一门编程语言的正轨。本文作者使用了 Go 语言完成了曾经用 Python 搞定的多种任务,对比发现,Go 语言的方法似乎更胜一筹。其中,完成的任务比如说:

  • 处理 S3 上存储的 Cloudfront 日志;
  • 在 S3 中将 TB 级别的数据从一个桶移到另一个桶,或者其他区域;
  • 比较数据库中的数据和 S3 中的文件,确保数据的同步。

许多都是一次性的任务,因此脚本语言很合适。程序要能很快写出来,而且基本上用完就不会再用了。通常每次任务都是全新并且唯一的,因此几乎没有代码重用的可能。

下面是 Go 比 Python 强的地方:

编译器很好

我在 Python 中一直犯愚蠢的错误。比如搞错变量名或函数名,或者给函数传递错误的参数。Devtools 能发现一些错误,但通常这些工具需要特别设置。我从来没能完美设置好 pylint,我也不喜欢那些需要单独配置的笨重的 IDE。

最糟糕的情况是隐藏在条件逻辑后面的错误变量名。代码会运行几个小时,直到错误触发。然后就不得不一切从头开始。

单元测试通常能捕获这些错误,但很难获得 100% 的代码覆盖率,而且对于一次性的脚本我也不想浪费时间写测试。

编译语言能完全避免这些问题。编译器能找出所有愚蠢的错误。因此,对于任何超过 100 行代码的任务,我更喜欢使用 Go。

开发速度

编译器的缺点就是通常会降低开发速度。尤其在 C/C++ 和 Java 上特别明显。

但 Go 非常简单,我发现它对开发速度的影响非常小。不要误会,我用 Python 依然更快,但用 Go 通常能达到 Python 的 85% 效率。

考虑到使用编译器能犯更少的错误,85% 已经非常值得了。

更好的并发性

你一定知道,Go 的开发目的就是并发执行。

在我的团队中我们一般都需要并发编程,因为我们要处理 S3 或数据库中的海量数据

如果任务中有很多 IO(许多任务都是如此),那我们可以用 Python 的线程。但如果需要很多 CPU,那 Python 就很难办,因为它有全局解释器锁(Global Interpreter Lock)。

而使用 Go 的多线程,无需任何特殊处理就能正常工作,这一点非常棒。你一定体会过在 Python 中按 Ctrl-C 试图结束多线程任务却毫无反应的情况吧?

更容易部署

我喜欢单一的二进制文件。通常我在 EC2 机器上运行代码,使之在网络上更靠近与 S3 和数据库。使用 Python,我需要在远程机器上安装所有的包,并确保其他人没有安装任何冲突的东西。

虽然 Virtualenv 能解决这个问题,但我依然认为 Go 更容易。

通常我会在我的 Mac 上将代码交叉编译成 Linux 二进制文件,然后复制到远程机器上,然后就可以执行了。所有依赖都被放到二进制文件中了。

一致的风格

最初,gofmt 工具的确挺烦人,特别是他们使用 tab 而不是使用空格。我认为他们简直是疯了。

但用得多了后,我开始依赖它了。它能直接提供完美的代码格式。不管是哪个项目,所有代码都有同样的风格,因为风格就是标准 Go 工具链中的一部分。

而在 Python 中达到同样的效果需要更多的功夫。必须正确配置 pylint,并保证每个项目的配置都是一样的。

更好的工具链

gofmt 只是通用工具链的一个例子。所有我喜欢的编辑器,不论是 VSCode、vim 还是 SublimeText,都有非常好用的 Go 语言扩展,使用标准的 Go 工具链。

因此,我能获得近似 Java 的只能提示,但无需使用真正的 IDE。而使用 Python 就从来没能享受过这样的功能。

缺点

我读到的许多批评 Go 语言的文章都在说它缺乏某个明显的功能,比如泛型。但没有泛型我也从来没遇到过麻烦。实际上 map 和 slice 能完成许多工作。不过我却有些其他的问题。

Go 是有观点的语言

首先,Go 可能是我用过的最有观点(opinioned)的语言了。从强迫使用 Tab 而不是空格(假设你用 gofmt),到强迫使用固定的目录格式,甚至强迫在GOPATH 环境变量中写代码,许多 Go 的东西都没办法改变。

有观点的理由之一就是这样易于学习,因为这些特点都不会改变。但如果你不想导出的名字以大写字母开头,那就没办法了。不过幸运的是,这些问题都不会成为我不使用 Go 的理由,但我能理解有些人无法接受。

而 Python 则更灵活。

缺乏库支持

在这个领域比较 Python 和 Go 并不太公平。Go 非常年轻,但我还是会在发现 Go 本身不支持某个功能时感到很不解。更让我失望的是,一些人在 StackOverfolw 上贴了些本应是内置函数的代码,然后每个人都仿佛没事儿一样直接把代码粘贴到项目里使用。

举两个近几年我发现的例子:

  • 对 slice 排序(幸运的是在 Go 1.8 中变得容易得多了)
  • math.round 只能用于整数,而不能四舍五入成浮点数(比如四舍五入到最近的.5)。甚至在 Go 1.10 之前都没有 math.round。

当然,一些原因是因为 Go 没有泛型,一些是因为 Go 的设计思想就是只把绝对必要的东西加到标准库中。

我理解这两个原因,不过在遇到非常简单的功能却不得不自己写代码时还是觉得很烦人。

希望 Go 语言能越来越好,痛点能越来越少。

原文:
https://thinkfaster.co/2018/07/goodbye-python-hello-go/

作者:Jake Wilson

译者:弯月,责编:屠敏

“征稿啦”

CSDN 公众号秉持着「与千万技术人共成长」理念,不仅以「极客头条」、「畅言」栏目在第一时间以技术人的独特视角描述技术人关心的行业焦点事件,更有「技术头条」专栏,深度解读行业内的热门技术与场景应用,让所有的开发者紧跟技术潮流,保持警醒的技术嗅觉,对行业趋势、技术有更为全面的认知。

如果你有优质的文章,或是行业热点事件、技术趋势的真知灼见,或是深度的应用实践、场景方案等的新见解,欢迎联系 CSDN 投稿,联系方式:微信(guorui_1118,请备注投稿+姓名+公司职位),邮箱(guorui@csdn.net)。