我与 Go 语言的这十年

AlysaConder 7年前
   <p>2007 年 9 月 20 日,关于设计一门全新语言的讨论正式开始,这门全新的语言,就是后来的 Go。时至今日,Go 语言已经发布到 1.9 版本,走过了整整十年的历程。在这十年间,Go 语言两夺 TIOBE 年度语言大奖(2009/2016),许多初创公司在早期使用 Go 进行开发,包括现在的云计算巨头 Docker,也由此催生出了 Kubernetes 这样的项目。在大洋彼岸的中国,Google Trends 显示 Go 的异常火爆更让 Go 语言之父感到震惊。而这一切,跟一位名叫许式伟的技术人密不可分。</p>    <p>Go 语言刚刚度过了它的十周年纪念日。而要说我与 Go 的缘分,也同样始于十年前(2007 年)。这十年,是 Go 成长的十年,同样也是我成长的十年。</p>    <p>2007 年 2 月,我建立了金山实验室,主攻分布式存储方向。这是我职业生涯至关重要的一个转折点。此前我已经做了 7 年的 WPS Office 办公套件的研发。这对我有两个重要的挑战:一个是角色转换上的,从做软件研发的架构师到做业务的产品经理;一个是技术领域变化上的,从单机的桌面软件开发到分布式的后端服务器开发。</p>    <p>我第一个面临的问题是技术选型。几乎没有作任何纠结,我们选择了 Java 作为主体的开发语言。作为初入后端开发领域的团队来说,这只是一个从务实角度出发的选择。但 TrustNo1 在程序员杂志发表的《一场茶杯里的风暴》一文让我认识了 Erlang 语言,并深深被 Erlang 的编程思想所打动。我意识到这种编程思想将会极大释放服务端编程的生产力。为了推动服务端最佳实践的探索,也为了进一步推动更多人了解和研究 Erlang,我发起了 ECUG 社区。ECUG 到现在已经十年。这十年我们风雨无阻,每年年底都会举行一场 ECUG Con 大会,和来自各行各业的技术大拿们齐聚一堂,大家一起分享这一年来服务端开发的实践心得。</p>    <p>尽管我们选择了 Java,但是随后我们也做了小范围使用 Erlang 进行开发的尝试。在 2008 年我们启动了一个用 Erlang 来编写存储系统(极简版)的业余项目。这次的尝试让我对 Erlang 有了进一步的判断:尽管 Erlang 的编程思想很好,但是 Erlang 语言本身并不适合大型的工程项目。</p>    <p>到了 2009 年 3 月,也就是我加入盛大创新院重启分布式存储项目时,我面临了第二次技术选型。这一次我选了最难的一条路:用 C++ 来开发。这是一条艰苦的路。促使我做出这一选择的最大原因是,我很希望能够制造一个新轮子,它应该既有 Erlang 编程思想的优势,又可以克服 Erlang 语言的劣势。如果这事能够干成,它将是一件伟大的创举,所有的服务端开发人员都将受益于此。于是,在心怀满腔热血之下,一个名为 CERL 的项目诞生了。在我们存储的第一个版本期间,实际上我们花费在 CERL 库的时间远超过了做存储本身,无论从代码量还是花费的精力来说都是如此。</p>    <p>CERL 项目经历了 2 个大的版本。CERL 1.0 完全遵循 Erlang 的编程思想,主要编程范式如下:</p>    <ul>     <li> <p>可以启动任意多的进程(这里进程是抽象的概念,实现上是纤程 / 协程),进程数上限只受限于内存大小。</p> </li>     <li> <p>每个进程有进程邮箱,相互发消息通过进程邮箱。</p> </li>     <li> <p>消息分同步消息和异步消息,同步消息会阻塞等待对方返回消息。</p> </li>     <li> <p>网络服务器是单进程模型(就是大家理解的单线程模型),一次只处理一个消息。</p> </li>     <li> <p>没有锁。</p> </li>     <li> <p>…</p> </li>    </ul>    <p>基于 CERL 1.0 的编程模型,我们实践中发现了这样一些问题:</p>    <ul>     <li> <p>在网络服务器 A、B 相互给对方发送同步消息时会发生“死锁”。因为双方可能都正在处理消息中而无法及时响应,这种“死锁”最终表现为超时(但是实际上超时更可怕,是服务器性能的杀手)。</p> </li>     <li> <p>解决“死锁”的方法是把同步消息改为异步,但是这对编程复杂性带来很大的影响,程序语义变得晦涩。本质上,这是回到了传统的异步编程模型,放弃了 Erlang 编程模型最大的优势。</p> </li>     <li> <p>“没有锁”的假设代价过高:在网络服务器的单个处理响应时间较长(存储服务必然如此)时,必然希望启动独立的进程来响应单个请求。但是各个处理请求的进程之间需要共享网络服务器的状态,这就意味着需要有锁(除非网络服务器是无状态的,但是很不幸存储服务器必然是带状态的)。要么放弃性能串行化地处理请求,要么有锁 —“没有锁”,想说爱你不容易。</p> </li>     <li> <p>…</p> </li>    </ul>    <p>在发现“死锁”问题后,我们立刻对我们整个编程模型进行了反思,决定重构整个编程模型,修改后的 CERL2.0 要点如下:</p>    <ul>     <li> <p>可以启动任意多的进程(这里进程是抽象的概念,实现上是纤程 / 协程),进程数上限只受限于内存大小。</p> </li>     <li> <p>没有进程邮箱。</p> </li>     <li> <p>进程之间只有同步消息(要发送异步消息,用启动一个新的进程并发送同步消息来达到同样的效果)。</p> </li>     <li> <p>网络服务器是多进程模型,每个请求都由一个独立的进程来处理。</p> </li>     <li> <p>有锁。</p> </li>    </ul>    <p>两个版本的编程模型的关键差异在于拒绝锁还是拒绝异步消息。CERL 1.0(也就是 Erlang 编程模型)中拒绝锁,而 CERL 2.0 拒绝异步消息。基于 CERL 2.0 我们实现了分布式存储的第二版、第三版。事实证明,完全杜绝了异步消息这个概念后,这个版本的服务器编程模型心智负担小了很多。</p>    <p>然后,如大家所知,后来 Go 语言就发布了。我们团队一看,在服务器编程模型这一点上,CERL 2.0 和 Go 语言居然一模一样(包括所有细节上的决策)。有一次团队聚餐谈起这事时,道哥(李道兵)说了一句:我们赶紧把 CERL 开源吧,不然等 Go 流行起来它就没机会了。我还真和创新院院长陈大年谈了 CERL 开源的事情,大年说:没问题,你发个邮件申请吧,留个凭证。然而我最终没有发出这封邮件。在尝试用 Go 写了一周的代码后,我心里已经有了结论:我并不打算让 CERL 面世。因为有人已经把它的目标完成了,而且远超预期。</p>    <p>于是,2011 年 6 月,我们离开盛大创新院创办七牛云的时候,我面临了第三次技术选型。这一次,我很坚决地选择了 Go 语言。为此我还专门给团队发了一封邮件,邮件中有一段是这么说的:</p>    <p>在创业过程中我们会面临很多选择,也会有很多选择后来会被证明是错的,但是今天我可以确定的是,选择 Go 将会成为我们最正确的选择。</p>    <p>在选择了 Go 语言后,考虑到 Go 仍然是一门十分小众的语言,我们开始有意识地培养 Go 中国社区。为了让更多人能够知道 Go,加入 Go 的行列,我们做了很多工作。我们启动了《Go 语言编程》一书的编写工作,并最终和 Go 1.0 版本同步发布。2012 年 2 月,我首次在公开场合说:Go 会超过 C、Java,成为最流行的语言。这一年我到处宣讲,做了不下十场的 Go 语言讲座,平均每个月有一场。讲得最多的一个 PPT 是《Go,Next C》这篇,它基本上算我对 Go 的革命性到底在哪里的一个总结。对于一个初创公司来说,为一个并不属于自己业务的技术这么花时间去宣传,有些人可能会觉得比较不可理解。但是实际上有三个理由支撑我们这么做:</p>    <ul>     <li> <p>Go 真的是一门革命性的语言,它的流行将对产业发展具重大意义。</p> </li>     <li> <p>Go 仍然是一门小众语言,而我们不止要招 Go 程序员,更重要的是要说服他们相信 Go 语言是有远大前景的专业技能方向。</p> </li>     <li> <p>七牛的用户是程序员,我们需要建立在用户心目中的专家形象。</p> </li>    </ul>    <p>七牛云的起步第一个业务是云存储,我们选择了完全用 Go 来实现我们的存储系统。这是全球第一个用 Go 写的云存储,也是第一个用 Go 写的云服务。而到了 2014 年,在我们决定进入大数据领域时,我们再一次面临技术选型问题。坦白说,我们还是纠结了一段时间的。从生态来说,选择 Java,或者某种 JVM 平台的语言(比如 Scala)有非常显著的优势。尤其对于我们大数据业务的负责人陈超这个 Scala 的狂热粉丝(八卦一下:陈超的网络 id 是 CrazyJVM),选择 JVM 平台似乎更加是毋庸置疑的选择。那么我们纠结什么呢?我们认为未来 Go 会占领整个基础设施领域,而大数据无疑是其中极具关键意义的一个领域。所以面向现在做选型,还是面向未来做选型,这是一个问题。</p>    <p>说到这里我提一个有意思的细节。在陈超刚加入七牛的时候,我对他说:“不管未来你会用什么语言,但是进入七牛必须要会写 Go。”于是他被我逼着写了一个月的 Go 代码。一个月后我问他感觉如何,他说:“能够理解为什么你推荐 Go 了,写了 Go 代码后不想回去写 Scala 代码。”不久之后,在他启动 Pandora 大数据平台项目时,就碰到了我说的选型问题。在做了非常细致的思考之后,他决定用 Go 做 Pandora。这对我来说是一个意料之外的决策。因为我自己在这个事情上并没有倾向性,而陈超我觉得他很可能还是会优先选 Scala。就在最近(国庆节前)某次聊天中,陈超回顾起这件事,总结了一下他为什么选择了 Go:极低的学习成本,极低的心智负担。如果用 Scala,新人入职要培训,还要担心写出糟糕的 Scala 代码。但是用 Go 新人不培训直接上岗,几次 Code Review 完后基本就能够知道怎么写出质量不错的 Go 代码了。</p>    <p>十年过去,Go 已经不再是一门小众语言。越来越多人在用 Go,喜欢上 Go。不记得是什么时候了,但是某一天通过 Google Trends 搜索 golang 发现全世界 Go 最火的地区是在中国时,那一刻真的很开心。</p>    <p>下一个十年会怎样?我知道有一些人很期望 Go 语言特性的迭代。但是如果你抱有这种想法可能会失望,因为下一个十年 Go 不会发生太大的变化。对远期需求变化的预测和把控能力,是 Go 的最大魅力之一。这一点上能够和 Go 相比的是 C 语言(C 语言不同版本的规范差异极少),但因为 Go 要解决的问题更多,做到这一点实际上也更难。下一个十年 Go 仍然会继续深耕服务端开发的生态,同时积极探索其他潜在的应用市场。</p>    <p>延展阅读</p>    <p>在 QCon 2015 上海站上,许式伟曾经做过《Go 语言发展状况》的主题分享。对于 Go 语言,他提到过三个预测:</p>    <ul>     <li> <p>第一个预测,我最早在 2012 年新浪微博里提过,Go 语言 10 年内一定会超过 C 和 Java,变成排行榜第一的语言。今天大家可能会略相信,但在 2012 年的时候没有多少人会相信,即使今天讲出来,绝大部分人都会觉得太早,毕竟它还没有排进前五。</p> </li>     <li> <p>第二个预测,Go 语言将在两年内制霸云计算领域。</p> </li>     <li> <p>第三个预测,Go 将统治下一个 10 年。(来自于 Deferpanic 创始人 Lan Eyberg)。</p> </li>    </ul>    <p>最新动态</p>    <p>12月17日在上海举办的 ECUG Con 十周年盛会中,许式伟提出,Go在占领了云计算领域后,下一个战场会是在游戏领域!并且进行了细致的分析,演讲内容也将在 Go 中国公众号上公布,敬请期待~</p>    <p> </p>    <p>来自:http://mp.weixin.qq.com/s/iU7gaZNgCsU3DHaHa5PZ_Q</p>    <p> </p>