为什么你需要学 Go?

file

"Go 将是未来的服务端语言。" --- Tobias Lütke, Shopify

在过去的几年中,有一颗语言之星冉冉升起: Go 或 GoLang。没有什么东西比一门新编程语言能让开发者痴狂的了,你说对不对? 所以呀,我大概 4 ,5 个月之前就开始学 Go 了,这里我来讲讲为啥你要学这门新语言。

在这篇文章里,我并不打算教你怎么写个「Hello World!!」。线上已经有很多这种教程了。我打算基于当今计算机硬-软件阶段来讲一下,为什么我们需要类似于 Go 的这种新兴语言?因为如果没什么问题,我们也不需要解决方案,对吧?

硬件限制:

摩尔定律 正在失效
英特尔于 2004 年发布了第一块具有 3.0GHz 时钟速率的 Pentium 4 处理器。
而今, 我的 Mackbook Pro 2016 的 CPU 时钟速率是 2.9GHz。因而,在过去的十年间, CPU 的处理能力没有太大的发展。你可以从下图中看到这一点。

file

从上图中可以看出,在过去十年间单线程的性能和处理器的速率保持稳定。倘若你把增加晶体管的数量作为解决方案,那么你错了。
因为在较小的尺度上开始出现一些量子特性(如:隧穿效应),这将导致放置更多晶体管实际上花费更多(为什么)并且增加晶体管的性价比在下降。

所以,为解决以上问题

  • 制造商开始向处理器添加越来越多的核心。现在我们有四核和八核CPU可用。
  • 我们还引入了超线程。
  • 向处理器添加更多缓存以提高性能。

但是上述解决方案也存在其局限性。我们并不能通过塞更多到缓存到处理器中来提高其性能,因为缓存本身有其物理特性限制:缓存越大,它就越慢。向处理器中加更多内核一样会有其开销。此外,它也不可能无限缩小。多核处理器可以同时跑多个线程,但是它也会带来图像处理上的并发问题。我们一会再讨论这个问题。

所以,如果我们不能依赖硬件去改善我们的处境,剩下的出路就是从更高效的软件来作为提升性能的落脚点了。但很遗憾,现代编程语言的效率普遍都不高。

「现代处理器就像一触即发的改装车,四分之一英里加速赛表现卓越。但是不幸的是现代编程语言却像蒙特卡洛的F1赛道,迂回曲折。」 --- David Ungar


Go 拥有 goroutines !!

如上所述,硬件制造商正在向处理器添加越来越多的核心以此来提高性能 。我们可以预期,在未来几年所有使用这些处理器的数据中心的处理器核心数还会增加。 更重要的是, 今天的应用程序使用多个微服务来维护数据库连接、消息队列和缓存。因此,我们开发的软件和编程语言应该更容易的支持并发性并且应该随着核心数的增加更容易的扩展。

但是, 大多数的现代编程语言(如 Java,Python)诞生于上世纪 90年代的单线程环境。虽然大多数的编程语言支持多线程,但是真正的问题来自于并发执行,线程锁,竞争条件和死锁。这些问题导致使用这些编程语言创建多线程应用程序相当困难。

举例来说,在 Java 中创建新线程并不高效。 由于每个线程大约消耗 1 MB 的堆内存,一旦让千计的线程开始自旋,它们将对堆内存造成极大的压力,可能会因内存不足而崩溃。另外,如果你想让两个以上的线程之间进行通信,也是非常困难的。

另一方面,早在 Go 发布之初的 2009 年已经有了多核处理器了。这也是 Go 为什么建立在保持并发设计基础上的原因。 Go 使用 goroutines 代替线程。每个 goroutine 大概消耗 2KB 的堆内存。所以在任意时刻都可以自旋百万计的 goroutine 。

file

Goroutines 如何工作? 请参阅:http://golangtutorials.blogspot.in/2011/06...

当然还有如下优点:

  • Goroutines 拥有有可增长的分段堆。这意味着它们仅在需要时才使用更多的内存;
  • Goroutines 拥有比线程更快的启动时间;
  • Goroutines 拥有内置的原语,以便在他们(channels)之间安全的通信;
  • Goroutines 允许你避免在共享数据结构时使用互斥锁;
  • 此外,goroutines 和 OS 线程不是 1:1 映射 。单个 goroutine 可以在多个线程上运行。Goroutines 被复用到少量的 OS 线程中。

推荐去看下 Rob Pike's 精彩演讲 并发不是并行 可以加深对此的理解。

上述的要点让 Go 可以强大得像 Java,C 和 C++ 一样处理并发,同时又能像 Erlang 一样优雅的执行并发代码。

file

Go 博采众长,使得它易于高效地编写和管理并发代码。


Go直接运行在底层硬件。

C , C++ 优于其他现代高级语言(如Java / Python)的一个最大优点就是它们的性能。因为 C/C++ 是被编译的而不是被解释。

处理器理解二进制文件。通常,当编译利用 Java 或其它基于 JVM 的语言构建的应用程序时,这会将人类可读的代码编译为字节代码, JVM 或其它运行在底层操作系统之上的虚拟机可以理解这些代码。在执行时, VM 解释这些字节码并将它们转换为处理器可以理解的二进制文件。

file

基于 VM 语言的执行步骤

另一方面, C/C++ 并不在虚拟机上执行,它从执行周期中省去了这一步从而提升了性能。 它直接将人类可读的代码编译成二进制文件。

file

但是,释放和分配变量是这类语言的一大痛处。而大部分语言都使用垃圾收集器和引用计数来处理对象分配和回收问题。

Go 取二者之长。 类似比较低级的C/C++这样的语言, Go 是一种编译型语言。也就是说,它的性能几乎和低级语言一样强悍。它同样也具备垃圾回收机制。 所以,不需要什么 malloc() 和 free() 之类的语句了!!! 酷毙了!!!


Go 编写的代码易于维护

一事相告,Go 并没有像其他语言那样有各种繁复的语法,它简洁明了。

Go 语言的缔造者者在创世之初就高瞻远瞩。Google 拥有海量代码库,成千上万的开发者徜徉其中使用着相同的代码库,所以代码的易读性和隔离性就很有要求,Go 语言正为此而生。

Go 舍弃了现代 OOP 类型的语言的很多特性。

  • 无类。所有事物都被划分到包中。Go 中只有结构体,它取代了类。
  • 不支持继承。这就使得代码非常易于修改。在其他语言例如 Java/Python 中,如果类 ABC 继承了类 XYZ ,如果想改动类 XYZ, 就会对继承了 XYZ 类的其他子类产生影响。通过移除继承,Go 同样也让代码变得易懂 (因为追一段代码时没有父类)
  • 没有构造方法。
  • 没有注解。
  • 没有泛型。
  • 没有异常。

上述的改变使得 Go 和其他语言编程风格迥异。或许你不太喜欢。但是,并不是离开了以前那些语言特性我们就对写代码束手无策了。无非就是多 2--3 行代码的事。但从积极方面来看,它会令代码更加整洁清晰。

file

代码的可读性 vs 执行效率。

上述统计图反映出 Go 执行效率直逼 C/C++,同时语言简单的类似 Ruby, Python 之类的语言。它做到了人类和处理器之间的双赢。

异于其他类似 Swift 的新语言,Go 的语法非常稳定。自 2012 年发布以来,它一直保持不变,保持了向后兼容性。

Go 的背后是 Google。

  • 我知道这并非一个很直接的技术优势。但 Go 是由 Google 设计并支持的语言。 Google 是全球最大的云基础架构商之一,其体量繁杂庞大。Go 由 Google 设计,旨在解决其伸缩性和效率问题。这些问题都是在创建服务器时都会面临的。
  • 更有说服力的是, Go 同样也被一些诸如 Adobe,BBC, IBM, Intel 甚至 Medium (源自: https://github.com/golang/go/wiki/GoUsers ) 这类大公司使用。

结语:

  • 尽管 Go 和其他面向对象型语言千差万别,但是其性能不遑多让。 Go 拥有 C/C++ 一样的高性能,Java 一样的超高效并发处理,Python/Perl 一样的有趣语法。

  • 如果你没有学习 Go 的想法,我仍旧会告诉你,硬件的限制会给我们带来压力,软件开发者需要编写超高效的代码。开发者需要了解硬件尽可能地优化其程序。优化过的程序可以运行在更廉价更慢的硬件上 (例如 IOT 设备) 并且用户体验会更上一层楼。


~如果您喜欢这篇文章,请点击下面的 ? 此外,您可以在 Medium 或者 我的 博客 上关注我,这样您可以在Go !!上获得后期文章的更新!!~

0

鸣谢

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://medium.com/@kevalpatel2106/why-s...

译文地址:https://learnku.com/go/t/23384

本文为协同翻译文章,如您发现瑕疵请点击「改进」按钮提交优化建议
讨论数量: 2

并发和并行的关系那里,之前我也搜了很多,看了一些云里雾里,后来去看《深入理解计算机系统》第三版里面的解释,我看了之后理解是这样的:并发囊括了并行,并行是并发的一种特殊形式,做事情的时候,时间线有重叠就是并行的。浅见,见笑。

2年前 评论
makingBug 10个月前
JaguarJack

@wilson_yang 多核和单核的区别

2年前 评论

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!