今天在Medium看到一篇“Why should you learn Go?”,自己也是处在学习Golang的初级阶段,觉得这篇文章对初学者有很大的益处,获得原作者的同意后,决定把它翻译成中文。译者水平可能不高,文章如有错误,请指正,本人感激不尽。
“Go will be the server language of the future.” — Tobias Lütke, Shopify
在过去的几年里,有一种新的编程语言热度在持续地上涨:Go或者叫Golang。唯一能让程序员疯狂的事,只有新出的编程语言了,对吧?因此,四五个月之前我就开始学习Go语言,并且打算告诉你为什么你也应该学习这门新语言。
在这篇文章中,我不是要教你如何写”Hello World!“,网上有很多这样的教程。接下来我将阐述当前计算机硬件-软件所处的阶段以及为什么我们需要类似Go的新语言。也许我们认为,没有出现问题,所以我们也不需要解决,这样的想法对吗?
硬件限制:
摩尔定律 正在失效。
2004年英特尔推出了第一款具有3.0GHz速度的Pentium 4处理器。今天,我的Macbook Pro 2016已经有了2.9GHz的速度。在这十年间,原生的处理速度并没有多大的进步。在下表中你可以看到这期间处理能力的对照情况。
从上图可以看出,单线程性能和处理器的频率在近十年内保持稳定。如果你认为增加更多的晶体管是解决方案,那么你就错了。这是因为在更小规模的情况下一些量子特性开始出现(如隧道),也因为它实际上要投入更多的晶体管(为什么?),并且每美元增加晶体管的数量开始下降。
因此,对于上述问题的解决方案,
· 制造商开始加入越来越多内核处理器。现在我们有四核和八核CPU可用。
· 我们还推出了超线程技术。
· 为处理器增加更多的缓存提高性能。
但是,上述的解决方案本身的局限性太大。我们不能通过为处理器添加越来越多的缓存来提高性,因为缓存有物理极限:缓存越大,速度月满。处理器添加更多内核也有其成本。此外,不能扩展到无限。这些多核处理器可以同时运行多个线程,并带来并发。我们将在后面讨论。
所以,如果我们不能依靠硬件的改进,提高性能的唯一办法就是更有效的软件。但可悲的是,现代的编程语言的效率都不太高。
“现代处理器就像加满硝基燃料的汽车,它他们擅长的四分之一英里。不幸的是现代编程语言都像蒙特卡洛,他们充满曲折。“ — David Ungar
Go有go协程!!
正如我们上面所讨论的,硬件厂商正在给处理器添加更多内核来提高性能。所有的数据中心都在这些处理器上运行,我们应该期待在未来几年核心数量能够增加。如今的应用更多地使用多个微服务维护的数据库连接,消息队列和维护缓存。因此,我们开发的软件和编程语言应该很支持并发,并且它们应该支持内核的数量的扩展。
但是,大多数现代编程语言(如Java,Python等)诞生于上世纪90年代的单线程环境,这些编程语言大多数支持多线程。但真正的问题是并发执行,线程锁,竞争条件和死锁。这些问题导致了很难用那些语言创建多线程应用程序。
举个例子,使用Java创建新的线程在内存上并不高效。每个线程占用的内存堆大小约为1MB,如果你开启数千个线程,就会让堆承受巨大的压力,将会由于内存不足导致关闭。另外,如果你想两个或多个线程之间进行通信,这是非常困难的。
另一方面,Go语言是在2009年发布的,此时多核心处理器已经可用。这就是为什么Go在语言层次上支持并发,Go有go协程而不是线程。他们消耗的堆内存几乎只有2KB。所以,你可以随时启动数百万的go协程。
其他的优点:
· go协程有可增长的分段堆栈。这意味着,他们只在需要的时候才会使用更多的内存。
· go协程比线程启动更快。
· go协程配备了内置的原语,可以使它们(通道)之间的通信变得安全。
· go协程让你避免在共享数据结构时采取互斥锁。
· 此外,够程和OS线程不必1对1的映射。单个go协程可以在多个线程运行。go协程可以复用成少数OS线程。
你可以在的Rob Pike的演讲并发不是并行 获得关于go协程更深的理解。
以上各点,让Go可以像Java,C和C ++高效处理并发,同时像Earlang以简洁直观的代码执行并发。
Go直接在底层运行
使用C,C ++而不是其他现代高级语言如Java / Python中的一个最显着的好处是它们的性能。因为C / C ++编译型的而不是解释解释型的。
处理器理解二进制。一般来说,当你建立一个使用Java或其他基于JVM的语言的程序,当你编译你的项目,它把人类可读的代码编译成JVM或于底层的操作系统上运行的其他虚拟机可以理解的字节码。执行期间,虚拟机解释那些字节码并将它们转换成可以被处理器理解的二进制文件。
另一方面,C / C ++不在虚拟机上执行并且去除这一层次以提高性能。它直接把人类可读代码编译成二进制文件。
然而,在这些语言中释放和分配变量是一个巨大的痛苦,尽管大多数编程语言使用垃圾收集器或引用计数算法来处理对象的分配和释放。
Go语言兼顾了这两个方面。Go像C / C ++等低级语言,是编译型语言。这意味着性能几乎接近低级语言。它还使用垃圾收集来分配和清除的对象。因此,没有更多的malloc()和free()语句!酷!!!
Go代码易于维护
让我告诉你一件事。Go没有其它语言一样疯狂的编程语法。它的语法非常整洁,干净。
Go语言的谷歌设计者在创造这门语言的时候已经想到了这个事情。随着谷歌有非常庞大的代码库和数以千计的开发人员正在处理相同的代码库,代码应该很简单让其他开发人员理解并且一个代码段应该对代码的另一段的副作用应当最小。这将使代码易于维护,易于修改。
Go故意遗漏了现代OOP语言的许多特性。
· 没有类。所有的事情仅划分成包。同时,Go用结构体替代了类。
· 不支持继承。这将使代码易于修改。像Java / Python语言,如果ABC类继承的XYZ类并且你改动了XYZ类,那么可能在继承了XYZ的其他类中产生一些副作用。通过删除继承,我们可以很容易地理解代码同时(因为当看一段代码时,不用当成超类来看待)。
· 没有构造函数。
· 没有注解。
· 没有泛型。
· 没有exceptions(应该指的是像ava的错误类型)。
上述变化使Go与其他语言非常不同,也使使用Go语言编程不同于其他编程语言。你可能不喜欢上面的几点。但是,如果没有以上的几点特性,你不可能编写你的程序。你只需要做的是多写2-3行。好处是,它会使你的代码更加清晰。
上述图显示的是Go几乎与C / C ++一样高效,同时代码语法像Ruby,Python和其他语言一样简单,这是对人类和处理器的双赢!
不同于其他的类似Swift的新语言,Go语法是非常稳定的。它的语法从最初的2012年公开发行1.0之后一直未变,这使它支持向后兼容。
Go是Google支持的
· 我知道这是不是一个直接的技术优势。但是,很重要的一点是,Go是谷歌设计并支持的。谷歌拥有世界上最大的云基础设施之一,并且它的规模不断扩大。Go是由谷歌设计来解决他们的支持可扩展性和有效性问题。在创建自己的服务器,你将面临同样的问题。
· 更多的大公司,比如Adobe,BBC,IBM,Intel甚至是Medium都在使用Go。(来源:https://github.com/golang/go/wiki/GoUsers)
结论:
· 即使Go不用于其他面向对象的语言,它仍然不可忽略。Go提供了像C / C ++一样的性能,像Java一样的超高效的并发处理,像Python / Perl一样有趣的代码。
· 如果你没有任何计划去学习Go,我依旧认为硬件限制给了我们压力,从而软件开发人员可以编写出超级高效的代码。开发人员需要了解硬件,并对他们程序进行相应的优化。优化后的软件可以运行在更便宜和更慢的硬件上(如运行IOT设备)和最终用户的体验将得到更大的影响。
如若有错误之处,请指正~
有疑问加站长微信联系(非本文作者)