修正:我知道我没有把本文的观点表述清楚。我不会说GO语言有问题,或者它应该做些什么改变,因为它跟Erlang语言不一样。我准备说的是GO所做的选择让它难以与Erlang在实用性和低响应高并发需求的后台应用上抗衡。有必要注意一下,我不会写像Julia语言一样的东西。我听说不管是新项目还是老项目,GO都被定位为Erlang的竞争对手。没有人会对JULIA语言说这样的话,但GO和Node.js倒是被一些人看作是Erlang很好的替代品。Erlang不能解决所有的问题!本文主要谈论的是哪些地方Erlang适合使用而GO却不适合使用。
我打算不带主观意见,用公正的眼光来看待GO,先将自己对它不喜欢的部分遗忘,比如说语法或缺乏模式匹配,并且解释语言本身和运行环境的类型系统的某些不适应的客观原因。虽然它有很多缺点,但我打算先从其好的部分说起。
GO语言的亮点
客户端
正如Rob Pike所写的,它最大的惊喜就是GO语言吸引了许多Python和Ruby的开发人员,而不是C++的。对于我来说我很乐于看到这种趋势。不再有用pip和gems安装的运行速度慢的客户端了!(虽然由于某些原因Node.js用于客户端的人数在增加,TMD keybase呢?)
GO通过垃圾回收和并发原语能让开发人员快速,简单的使用高级,静态语言。同样地,这也可能是C++转战GO的一个重要因素,在我电脑上跑着的程序(Hipchat和Spotify)经常崩溃都是因为C++喜欢滥用内存。但Rob Pike指出C++的开发人员不想使用简单强大的GO语言。但Ruby和Python开发人员很乐意转战GO。
工具
在不依赖于第三方工具的情况下能轻松使用第三方库来构建可执行文件,这都是GO的亮点。虽然这些工具不太完美,但有一些工具能弥补这些缺点,比如说Godep。对于GO来说这也是一大胜利。
GO的不足之处
当GO被用来写低延迟容错系统的时候,它的一些设计决策是有害的。
并发性
是的,在第一部分我已经额外的提到了并发原语。这是GO在替代Ruby,Python或C++作为客户端语言的情况下作出的说明。但当需要写容错的后台程序时,在共享状态方面GO和其它语言一样烂。
抢占式调度
在这方面GO语言要好一些。GO语言的抢占式调度是针对系统调用的,但现在,当goroutine检查所有函数调用的堆栈时抢占就能发生,如果goroutine的运行周期比以前的长,那么这很可能会被标记为失败(这将会造成抢占)。虽然这是一种进步,但还是滞后于Erlang的减少计算和最近为改进C集成而新增的脏调度。
垃圾收集
在GO中垃圾收集是全局标记和清理垃圾的。在清理垃圾时会暂停所有的goroutine,而且等待时间很恐怖。低等待时间是很困难的,执行时间越长,它就能为你做的越好。
错误处理
如果返回值为nil,不仅仅只是没有异常和使用检查。Goroutine没有身份标识,这意味着GO缺乏连接和监控goroutine的能力。没有连接(它使用的是panic和defer)和进程隔离,意味着你不能以稳定的状态避免死机和重启。在产品中会有BUG,而且许多BUG都是Heisenbugs,所以能让进程与进程之间隔离开来但要基于他们之间依赖,是容错的关键。
在处理错误的重大遗漏上,GO有nil。它在2014年是如何被认为可以的,目前我脑海中还没有任何概念。先不管它,稀里糊涂的看看再说。
内省
没有REPL对开发来说是一件恼人的事,但没有远程shell来运行系统是更让人烦恼的事。Erlang有骄人的追踪能力,一些工具是建立在这些能力上的,比如recon_trace。Erlang的内省很好的改善了开发,同时也能更好的维护复杂的系统。
静态链接
是的,同样积极正面的一个东西,但如果用在期望运行时间很长的系统上它就变得消极了。虽然没有链接执行确实会比较慢,但这却给了Erlang在运行系统上代码替换方面的优势。很有必须说明一下,由于Erlang的调度和垃圾收集策略,许多这些速度权衡并不意味着Erlang在同样的应用中会比其它语言慢,特别是如果Erlang应用是唯一一个仍在运行的。
代码组织
OTP框架为通用模式提供了库。OTP不仅意味着更少的代码和更好的抽象,同时也意味着更好的可读性。随着应用的OTP标准,管理人员和工人(gen_server, gen_fsm, gen_event)意味着程序的新开发人员能够通过进程树很好的工作,同时也表明他们之间是如何交互的。GO的channel,不可识别的goroutine和缺乏模式将goroutine分割成独立的模块会让代码变得更难写。
GO能改变、应该改变吗?
Erlang已经问世数十年了,而GO是新产品,那么GO能在这些领域得到改善吗?有些地方是可以的,但由于语言设计本身缺乏容错和低延迟,它在绝大地方都不能改善现状。
这并不是说GO不好或者它设计得有误。它的这些不同能让其它像Erlang这样的语言更好的解决不同的问题。
原文 blog.erlware.org