“Go将成为未来的服务端语言。” --Tobias Lütke, Shopify
在过去的几年中,崛起了一门新的语言:Go,也称作GoLang。作为一名开发者,没有什么比一门新的编程语言更让人兴奋的了,所以,我在四五个月之前开始了Go的学习。通过本文,我将告诉你,为什么你也应该来学习这门新的编程语言。
在本文中,我不会教你如何写出"Hello World!!"。这样的教程网络上已经有很多了。我将在本文中阐述,软硬件目前的发展现状,以及,在这样的形势下,我们为什么要学习像Go这样的新语言。因为存在问题,所以需要找到解决方案。
硬件的局限性
摩尔定律在失效。
2004年,英特尔公司推出了第一款具备3.0GHz主频的奔腾4处理器。而如今,我的2016款Macbook Pro也只有2.9GHz的主频。因此,原始处理能力在过去的十年中,基本没有什么提升。下图清晰地展示了处理能力的增长与时间之间的关系。
从上图中我们可以看出,单线程的性能和处理器的频率在近十年的增长几乎持平。如果你认为添加更多的晶体管可以解决的话,那你就错了。因为在微观尺度上,量子特性开始显现(例如:量子隧道穿越),放更多的晶体管成本也会越高(为什么?),并且,单位美元可以添加的晶体管数量也开始下降。所以,针对上述问题,解决方案如下:
- 厂商开始向处理器添加更多的内核。当今,我们有四核和八核的 CPU 可用。
- 引入了超线程技术。
- 为处理器添加更多的缓存以提升性能
但是以上方案自身也存在局限性。由于缓存自身的物理限制:缓存越大,速度越慢,所以我们无法一直向处理器增加缓存来提升性能。向处理器添加更多的内核也存在它的成本。这样的扩展也是有限的。这些多核处理器可以同时运行多个线程,从而实现了并发性。我们稍后会讨论它。
因此,如果我们无法依赖于硬件提升,那唯一的出路只能是通过更高效的软件来提升性能。但遗憾的是,现代编程语言都不太高效。
“Modern processors are a like nitro fueled funny cars,they excel at the quarter mile. Unfortunately modern programming languages are like Monte Carlo,they are full of twists and turns.” --David Ungar
Go 拥有 goroutine!!
如上所述,硬件厂商通过向处理器添加更多的内核来提升性能。所有的数据中心都运行在这些处理器上,我们应该期待在未来几年内核数量的增长。更进一步,如今的应用程序均使用多个微服务来维持数据库的连接、消息队列和保持缓存。因此,我们开发的软件和编程语言应该更容易支持并发,并且,随着内核数量的增长,它们应该是可扩展的。
但是,大多数现代编程语言(如 Java、Python 等)均来自于90年代的单线程环境。这些语言虽然大都支持多线程,但真正的问题是并发执行、线程锁、竞争条件和死锁。这些问题使得很难在这些语言上创建一个多线程应用。
例如,在 Java 中创建新的线程,内存的利用率并不高效。每个线程会消耗大约 1 MB 的堆内存,最终,如果你运行了上千个线程,他们会对堆带来巨大的压力,并且会由于内存不足而宕机。另外,你想要在两个或者多个线程之间通信,也是非常困难的。
另一方面,Go 于 2009 年发布,这时多核处理器已经可用了。这也是为什么 Go 在构建时会考虑保证并发性。Go 拥有 goroutine 来替代线程,单个goroutine消耗大约 2 KB 的堆内存。因此,你可以随时启动上百万个 goroutine。
其他好处:
- Goroutine 具有可伸缩的分段堆栈(版本1.4以后,已改为连续栈),这意味着在需要的时候才会使用更多的内存。
- Goroutine 比线程启动得更快。
- Goroutine 自带安全通信协议,channels。
- Goroutine 允许你在共享数据结构时避免使用互斥锁。
- 此外,goroutine 和系统线程没有1:1的映射关系。单个goroutine能在多个线程上运行。Goroutine 也能被复用到少数的系统线程上。
你可以通过 Rob Pike 的演讲并发不是并行加深理解。
基于以上几点,使 Go 能像 Java、C 或者 C++ 一样拥有强大的并发处理能力,而且能像Erlang一样,保证并发执行代码严谨性的同时,还能十分优雅。
有疑问加站长微信联系(非本文作者)