[译]为什么你要学Go?

本文译自Why should you learn Go?

几年前兴起了一门新的编程语言: Go,或者说 Golang 。没有什么能比一门新的编程语言更能让工程师感到兴奋了。所以我从四五个月前开始学习 Go ,并在此告诉你你为何也需要学习这门新语言。

我不会教你怎么写个 “Hello World” ,因为网上有太多文章能让你学了。我要讲的是当前的计算机软硬件情况以及我们为什么需要像 Go 这样的语言。毕竟没有问题就不会需要解决方案,对吧?

硬件限制

摩尔定律正在失效。

英特尔 2004 年发布了 3.0GHz 的奔腾4处理器。现在,我的 Mackbook Pro 2016 的 CPU 是2.9GHz 的。所以在最近的 10 年中,纯处理器性能并没有得到多大的提升。看看下面的处理性能-时间对照图表。

从上面的图表可以看到差不多最近十年的单线程性能和处理器的频率都没有再提升。如果你认为增加更多的晶体管就能解决问题,那你可就错了。原因有:在微观的角度上,量子方面的影响开始显现(比如隧道效应),即放越多晶体管实际损失会越大;更实际的角度上讲,晶体管数量越多,每花一块钱能增加的晶体管数也就越少。

因此为了解决上面的问题,

  • 处理器制造商开始增加更多的处理器核。如今我们能用上4核甚至8核的处理器了。
  • 引进了超线程技术
  • 在处理器中增加了更多的缓存来提高性能

但是上面的解决方法也都有它们本身的限制。我们不能通过增加越来越多的处理器缓存来提高性能,因为缓存本身就有其物理上的局限:缓存越大,去读缓存的速度就越慢。增加更多的核也会产生一些代价,也就不能无限地增加核地数量。多核处理器可以同时运行多个线程因此会带来需要处理多并发的场景,我们之后会讨论这个问题。

所以如果我们不能依赖硬件提升,就只能期望更有效率的软件来提升性能了。但是很遗憾,现代编程语言不那么有效率。

Go 的 goroutines

如上面的讨论,硬件制造商正增加越来越多的处理器核来提升性能。所有的数据中心都运行在这种处理器上,我们可以预料在未来几年核数还会提升。另外,今天的应用程序会使用多种维持数据库连接、消息队列和维护缓存的微型服务。因此我们所开发的软件和编程语言应当很容易地支持并发,并且要具有随着核数的增加而扩展的特性。

但是大多数现代编程语言(比如 Java 、 Python 之类的)都诞生于上世纪90年代那个只有单线程的世界。虽然大多数这样的编程语言支持多线程,但是真正的问题是并行计算、线程锁、竟态条件和死锁。这些东西令使用这些语言来创建多线程应用变得很困难。

举个栗子,在 Java 中创建一个新线程挺浪费内存的。每个线程都要消耗大约 1MB 的堆空间,并且如果同时运行上千个线程,堆空间会承受巨大的压力以至于内存溢出导致宕机。还有如果你想进行两进程或多进程间通信是十分困难的。

另一方面, Go 发布于 2009 年,那时多核处理器已经很流行了。这也是为什么 Go 以对并发编程有良好支持为己任。Go 提供的“线程”不是操作系统级别的线程,而是由 Go 在此基础上实现的 goroutines 。一个 goroutine 只会消耗大约 2KB 的堆空间。所以你当然可以在任何时候挥舞上百万个 goroutine 。

还有其它好处:

  • goroutine 具有可增长的分段堆栈。这意味着它只会在需要的时候才去占用内存。
  • goroutine 的启动时间比纯线程更快。
  • goroutine 内置的原语可以安全地进行彼此间的通信(名叫 channel)。
  • goroutine 允许你在共享数据结构时不必非得使用互斥锁。
  • goroutine 和操作系统层面地线程并不是一一对应的。一个 goroutine 可以运行在多个线程上。goroutine 是对一小部分操作系统线程的多路复用。

上述所有的优点让 Go 能够像 Java 、C 和 C++ 那样强有力地处理并发,并同时能像 Erlang 那样将并发计算的代码编写得直白又优雅。

Go 可以直接在底层硬件上运行

使用 C 和 C++ 相较像 Java、Python 这种现代高级编程语言最大的优势就是性能。因为 C/C++ 是直接被编译成机器码而不是通过解释器被执行。

处理器能够读懂机器码。通常当你使用 Java 或其他基于 JVM 的语言来构建应用时,你开始编译,只是将人类可读的代码编译成 JVM 或其他同样运行在操作系统上的虚拟机可以理解的字节码罢了。执行的过程便是由 VM 来解释这些字节码,将它们转换为处理器可以理解的机器码。

在 C/C++ 这边,它们不需要在虚拟机里执行,即在执行周期中去掉了一步从而提高了性能。它们直接从人类可读的代码被编译为二进制。

但是在这两种语言中释放和分配变量(译者注:原文为 freeing and allocating variable)又是很头疼的事。与此同时大多数编程语言会使用垃圾回收或引用计数算法来处理对象的分配和移除。

Go 就厉害啦,上面这俩优点都有。如相对更低级的语言 C/C++那样,Go 也是个编译语言。也就是说 Go 的性能是十分接近它们的。同时 Go 也有垃圾回收来处理对象的分配和移除。所以就没有像 malloc() 和 free() 这种语句啦,超酷对不对。

用 Go 写的代码很容易维护

Go 没有其它语言那样复杂的语法。它拥有非常优雅干净的语法。

在 Google 工作的 Go 的设计者们在设计这门语言之初就想到了这一点。因为 Google 拥有非常庞大的代码库,会有上千个开发者工作在同一个代码库中,代码对其他开发者应当简洁易懂,一个部分的代码对另一个部分的代码造成的影响应当尽量小。这将使代码易于维护和修改。

Go 有意地省去了许多现代面向对象语言拥有的特性。

  • 没有类。所有东西都仅使用包(package)划分。Go 只有结构体(struct)而没有类(class)。
  • 不支持继承。这将使代码易于修改。在 Java 或 Python 这样的语言中,如果类 ABC 继承类 XYZ,此时你改了类 XYZ 的东西,那么这也许就会影响到 ABC。通过干掉继承,Go 代码变得更加易于理解(因为这样的话你在看一段代码时就不用去找它的父级类了)。
  • 没有构造器(constructors).
  • 没有 annotations(译者注:由于译者只会写 JS 所以不知道这是啥)。
  • 没有泛型。
  • 没有异常。

上述革新令 Go 非常与众不同,同样,写起来也会感觉很不一样。你可能会不太喜欢上面所说的各种“没有”,但这并不意味着你做开发时离了它们就不行。你只要去写两三行代码就知道了。从积极的一面来看,这将使你的代码更清晰和干净。

上面的图表显示出 Go 是效率最接近 C/C++ 的语言,同时它的语法像 Ruby、Python 那样简单。它对人类和处理器来说是双赢的选择。

不像其它新语言比如 Swift,Go 的语法规则非常稳定。它从 2012 年发布 1.0 版本后语法就没变过。所以可以向后兼容。

Go 的爸爸是 Google

  • 我知道这并不是个直接的技术上的优势。但是 Go 是由 Google 设计和维护的—— Google 拥有世界上最大的云基建之一,并且还在一直大量地扩张。Go 是由 Google 设计去解决可扩展性和效率问题的——而你在创建你自己的服务器时也会面临同样的问题。
  • Adobe、BBC、IBM、Intel 甚至 Medium 都在用 Go。

总结

  • 尽管 Go 非常不同于其它面向对象语言,但它就是屌。Go 提供了如 C/C++ 一般的高性能,如 Java 一般的超强的处理并发的能力,如 Python/Perl 一般愉悦的编程体验。
  • 即使你并没有打算学 Go,我还是要说,硬件极限已经将压力推向了我们,逼迫作为软件开发者的我们写更有效率的代码。开发者需要去理解硬件,并根据硬件本身相应地去优化自己的程序。优化过的程序可以运行在更便宜、更慢的机器上,最终将更好的体验带给终端用户。
posted @ 2018-01-18 16:35  Sevenskey  阅读(159)  评论(0编辑  收藏