“ Go will be the server language of the future. ” — Tobias Lütke, Shopify
在过去几年,有一门崛起的新语言: Go 或者 GoLang 。没有什么比一门新的编程语言更令开发者兴奋了,不是么? 因此,我在 4、5 个月之前开始学习 Go。在这里我将告诉你,你为什么也要学习这门新语言。
在这篇文章中,我不打算教你怎样写 “Hello World!!”。网上有许多其他的文章会教你。**我将阐述软硬件发展的现状以及为什么我们要学习像 Go 这样的新语言?**因为如果没有任何问题,我们就不需要解决方案,不是么?
摩尔定律 正在失效。
英特尔公司在 2004 年推出 了第一款具有 3.0 GHz时钟速度的奔腾 4 处理器。如今,我的 2016款 MacBook Pro 的时钟速度为 2.9 GHz。因此,差不多十年,原始处理能力都没有太多的增加。你可以在下图中看到处理能力的增长与时间的关系。
从上面的图表可以看出,单线程的性能和处理器的频率在近十年几乎保持稳定。如果你认为添加更多的晶体管是一种解决问题的方法,那你就错了。这是因为在微观尺度上,量子特性开始显现(例如:量子隧道穿越),放更多的晶体管代价也会越多( 为什么? ),而且,每美元可以添加晶体管的数量也开始下降。
所以,针对上述问题的解决方案如下:
但是,以上方案也有它们自身的限制。我们无法向处理器添加更多的缓存以提升性能,因为缓存具有物理限制:缓存越大,速度越慢。添加更多的内核到处理器也有它的成本。而且,这也无法无限扩展。这些多核处理器能同时运行多个线程,同时也能带来并发能力。我们稍后会讨论它。
因此,如果我们不能依赖于硬件的改进,唯一的出路就是找到一个高效的软件来提升性能,但遗憾的是,现代编程语言都不是那么高效。
“现代处理器就像一辆有氮氧加速系统的直线竞速赛车,它们在直线竞速赛中表现优异。不幸的是,现代编程语言却像蒙特卡罗赛道,它们有大量的弯道。” - David Ungar
如上所述,硬件提供商正在向处理器添加更多的内核以提升性能。所有的数据中心都在这些处理器上运行,我们应该期待在未来几年内核数量的增长。更重要的是,如今的应用程序都是使用多个微服务来维持数据库的连接、消息队列和缓存的维护。因此,我们开发的软件和编程语言可以更容易的支持并发,并且它们应该随着内核数量的增长而可扩展。
但是大多数现代编程语言(如 Java、Python 等)都来自于 90 年代的单线程环境。这些语言大多数都支持多线程。但真正的问题是并发执行,线程锁、竞争条件和死锁。这些问题都使得很难在这些语言上创建一个多线程的应用程序。
例如,在 Java 中创建新的线程会消耗大量内存。因为每一个线程都会消耗大约 1 MB 大小的堆内存,如果你运行上千个线程,他们会对堆造成巨大的压力,最终会由于内存不足而宕机。此外,你想要在两个或者多个线程之间通信也是非常困难的。
另一方面,Go 于 2009 年发布,那时多核处理器已经上市了。这也是为什么 Go 是在考虑并发的基础上构建的。Go 用 goroutine 来替代线程,它们从堆中消耗了大约 2 KB 的内存。因此你可以随时启动上百万个 goroutine。
你能在 Rob Pike 的优秀演讲 并发不是并行 中获取更深刻理解。
以上这些点,能使 Go 能像 Java、C 或者 C++ 一样拥有强大的并发处理能力,同时在保证并发执行代码严谨性的基础上,像 Erlang 一样优美。
与其他现代高级语言(如 Java/Python)相比,使用 C、C++ 的最大好处就是它的性能,因为 C/C++ 是编译型语言而不是解释型语言。
处理器能理解二进制文件。通常来说,当你编译一个用 Java 或者其他基于 JVM 的语言构建的应用程序,它将人类可读的代码编译为字节代码,这可以被 JVM 或者在底层操作系统之上运行的其他虚拟机所理解。当执行的时候,虚拟机解释这些字节码并且将他们转化为处理器能理解的二进制文件。
而另一个方面,C/C++ 不会在 VM 上执行,并且从执行周期中删除(编译为字节代码)这一步提高性能。它直接将人类可读的代码编译为二进制文件。
但是,在这些语言中释放和分配变量是一件极其痛苦的事情。虽然大部分编程语言都使用垃圾回收器或者引用计数的算法来处理对象的分配和移除。
Go 做到了两全其美,Go 像一些低级别的语言(如: C/C++ )一样是一门编译型语言,这意味着它的性能几乎接近于低级别语言,它还用垃圾回收来分配和删除对象。因此,不再需要 malloc() 和 free() 声明了!!!这太酷了!!!
我告诉你一件事,Go 没有像其他语言一样疯狂于编程语法,它的语法非常整洁。
Go 的的设计者在谷歌创建这门语言的时候就考虑到了这一点,由于谷歌拥有非常强大的代码库,成千上万的开发者都工作在相同的代码库上,代码应该易于其他开发者理解,一段代码应该对另一段代码有最小的影响。这些都会使得代码易于维护,易于修改。
Go 有意的忽视了许多现代面向对象语言的一些特性。
以上这些改变使得 Go 与其他语言截然不同,这使得用 Go 编程与其他语言很不一样。你可能不喜欢以上的一些观点。但是,并不是说没有上述这些特性,你就无法对你的应用程序编码。你要做的就是多写几行代码,但从积极的一面,它将使你的代码更加清晰,为代码添加更多的清晰度。
如上图所示,Go 几乎与 C/C++ 一样高效,同时像 Ruby、Python 以及其他一些语言一样保持代码语法的简洁,对于人类和处理器来说,这是一个双赢的局面!!!
与 Swift 等这些新的语言不一样 ,Go 的语法非常稳定。自从 2012 年首次公开发布 1.0 版本以来,它保持不变并且向后兼容。