许式伟:我与Go语言的这十年[转]

简介: 2017-12-18 许式伟 Go中国 2007 年 9 月 20 日,关于设计一门全新语言的讨论正式开始,这门全新的语言,就是后来的 Go。时至今日,Go 语言已经发布到 1.9 版本,走过了整整十年的历程。

2017-12-18 许式伟 Go中国

2007 年 9 月 20 日,关于设计一门全新语言的讨论正式开始,这门全新的语言,就是后来的 Go。时至今日,Go 语言已经发布到 1.9 版本,走过了整整十年的历程。在这十年间,Go 语言两夺 TIOBE 年度语言大奖(2009/2016),许多初创公司在早期使用 Go 进行开发,包括现在的云计算巨头 Docker,也由此催生出了 Kubernetes 这样的项目。在大洋彼岸的中国,Google Trends 显示 Go 的异常火爆更让 Go 语言之父感到震惊。而这一切,跟一位名叫许式伟的技术人密不可分。

Go 语言刚刚度过了它的十周年纪念日。而要说我与 Go 的缘分,也同样始于十年前(2007 年)。这十年,是 Go 成长的十年,同样也是我成长的十年。

2007 年 2 月,我建立了金山实验室,主攻分布式存储方向。这是我职业生涯至关重要的一个转折点。此前我已经做了 7 年的 WPS Office 办公套件的研发。这对我有两个重要的挑战:一个是角色转换上的,从做软件研发的架构师到做业务的产品经理;一个是技术领域变化上的,从单机的桌面软件开发到分布式的后端服务器开发。

我第一个面临的问题是技术选型。几乎没有作任何纠结,我们选择了 Java 作为主体的开发语言。作为初入后端开发领域的团队来说,这只是一个从务实角度出发的选择。但 TrustNo1 在程序员杂志发表的《一场茶杯里的风暴》一文让我认识了 Erlang 语言,并深深被 Erlang 的编程思想所打动。我意识到这种编程思想将会极大释放服务端编程的生产力。为了推动服务端最佳实践的探索,也为了进一步推动更多人了解和研究 Erlang,我发起了 ECUG 社区。ECUG 到现在已经十年。这十年我们风雨无阻,每年年底都会举行一场 ECUG Con 大会,和来自各行各业的技术大拿们齐聚一堂,大家一起分享这一年来服务端开发的实践心得。

尽管我们选择了 Java,但是随后我们也做了小范围使用 Erlang 进行开发的尝试。在 2008 年我们启动了一个用 Erlang 来编写存储系统(极简版)的业余项目。这次的尝试让我对 Erlang 有了进一步的判断:尽管 Erlang 的编程思想很好,但是 Erlang 语言本身并不适合大型的工程项目。

到了 2009 年 3 月,也就是我加入盛大创新院重启分布式存储项目时,我面临了第二次技术选型。这一次我选了最难的一条路:用 C++ 来开发。这是一条艰苦的路。促使我做出这一选择的最大原因是,我很希望能够制造一个新轮子,它应该既有 Erlang 编程思想的优势,又可以克服 Erlang 语言的劣势。如果这事能够干成,它将是一件伟大的创举,所有的服务端开发人员都将受益于此。于是,在心怀满腔热血之下,一个名为 CERL 的项目诞生了。在我们存储的第一个版本期间,实际上我们花费在 CERL 库的时间远超过了做存储本身,无论从代码量还是花费的精力来说都是如此。

CERL 项目经历了 2 个大的版本。CERL 1.0 完全遵循 Erlang 的编程思想,主要编程范式如下:

  • 可以启动任意多的进程(这里进程是抽象的概念,实现上是纤程 / 协程),进程数上限只受限于内存大小。

  • 每个进程有进程邮箱,相互发消息通过进程邮箱。

  • 消息分同步消息和异步消息,同步消息会阻塞等待对方返回消息。

  • 网络服务器是单进程模型(就是大家理解的单线程模型),一次只处理一个消息。

  • 没有锁。

基于 CERL 1.0 的编程模型,我们实践中发现了这样一些问题:

  • 在网络服务器 A、B 相互给对方发送同步消息时会发生“死锁”。因为双方可能都正在处理消息中而无法及时响应,这种“死锁”最终表现为超时(但是实际上超时更可怕,是服务器性能的杀手)。

  • 解决“死锁”的方法是把同步消息改为异步,但是这对编程复杂性带来很大的影响,程序语义变得晦涩。本质上,这是回到了传统的异步编程模型,放弃了 Erlang 编程模型最大的优势。

  • “没有锁”的假设代价过高:在网络服务器的单个处理响应时间较长(存储服务必然如此)时,必然希望启动独立的进程来响应单个请求。但是各个处理请求的进程之间需要共享网络服务器的状态,这就意味着需要有锁(除非网络服务器是无状态的,但是很不幸存储服务器必然是带状态的)。要么放弃性能串行化地处理请求,要么有锁 —“没有锁”,想说爱你不容易。

在发现“死锁”问题后,我们立刻对我们整个编程模型进行了反思,决定重构整个编程模型,修改后的 CERL2.0 要点如下:

  • 可以启动任意多的进程(这里进程是抽象的概念,实现上是纤程 / 协程),进程数上限只受限于内存大小。

  • 没有进程邮箱。

  • 进程之间只有同步消息(要发送异步消息,用启动一个新的进程并发送同步消息来达到同样的效果)。

  • 网络服务器是多进程模型,每个请求都由一个独立的进程来处理。

  • 有锁。

两个版本的编程模型的关键差异在于拒绝锁还是拒绝异步消息。CERL 1.0(也就是 Erlang 编程模型)中拒绝锁,而 CERL 2.0 拒绝异步消息。基于 CERL 2.0 我们实现了分布式存储的第二版、第三版。事实证明,完全杜绝了异步消息这个概念后,这个版本的服务器编程模型心智负担小了很多。

然后,如大家所知,后来 Go 语言就发布了。我们团队一看,在服务器编程模型这一点上,CERL 2.0 和 Go 语言居然一模一样(包括所有细节上的决策)。有一次团队聚餐谈起这事时,道哥(李道兵)说了一句:我们赶紧把 CERL 开源吧,不然等 Go 流行起来它就没机会了。我还真和创新院院长陈大年谈了 CERL 开源的事情,大年说:没问题,你发个邮件申请吧,留个凭证。然而我最终没有发出这封邮件。在尝试用 Go 写了一周的代码后,我心里已经有了结论:我并不打算让 CERL 面世。因为有人已经把它的目标完成了,而且远超预期。

于是,2011 年 6 月,我们离开盛大创新院创办七牛云的时候,我面临了第三次技术选型。这一次,我很坚决地选择了 Go 语言。为此我还专门给团队发了一封邮件,邮件中有一段是这么说的:

在创业过程中我们会面临很多选择,也会有很多选择后来会被证明是错的,但是今天我可以确定的是,选择 Go 将会成为我们最正确的选择。

在选择了 Go 语言后,考虑到 Go 仍然是一门十分小众的语言,我们开始有意识地培养 Go 中国社区。为了让更多人能够知道 Go,加入 Go 的行列,我们做了很多工作。我们启动了《Go 语言编程》一书的编写工作,并最终和 Go 1.0 版本同步发布。2012 年 2 月,我首次在公开场合说:Go 会超过 C、Java,成为最流行的语言。这一年我到处宣讲,做了不下十场的 Go 语言讲座,平均每个月有一场。讲得最多的一个 PPT 是《Go,Next C》这篇,它基本上算我对 Go 的革命性到底在哪里的一个总结。对于一个初创公司来说,为一个并不属于自己业务的技术这么花时间去宣传,有些人可能会觉得比较不可理解。但是实际上有三个理由支撑我们这么做:

  • Go 真的是一门革命性的语言,它的流行将对产业发展具重大意义。

  • Go 仍然是一门小众语言,而我们不止要招 Go 程序员,更重要的是要说服他们相信 Go 语言是有远大前景的专业技能方向。

  • 七牛的用户是程序员,我们需要建立在用户心目中的专家形象。

七牛云的起步第一个业务是云存储,我们选择了完全用 Go 来实现我们的存储系统。这是全球第一个用 Go 写的云存储,也是第一个用 Go 写的云服务。而到了 2014 年,在我们决定进入大数据领域时,我们再一次面临技术选型问题。坦白说,我们还是纠结了一段时间的。从生态来说,选择 Java,或者某种 JVM 平台的语言(比如 Scala)有非常显著的优势。尤其对于我们大数据业务的负责人陈超这个 Scala 的狂热粉丝(八卦一下:陈超的网络 id 是 CrazyJVM),选择 JVM 平台似乎更加是毋庸置疑的选择。那么我们纠结什么呢?我们认为未来 Go 会占领整个基础设施领域,而大数据无疑是其中极具关键意义的一个领域。所以面向现在做选型,还是面向未来做选型,这是一个问题。

说到这里我提一个有意思的细节。在陈超刚加入七牛的时候,我对他说:“不管未来你会用什么语言,但是进入七牛必须要会写 Go。”于是他被我逼着写了一个月的 Go 代码。一个月后我问他感觉如何,他说:“能够理解为什么你推荐 Go 了,写了 Go 代码后不想回去写 Scala 代码。”不久之后,在他启动 Pandora 大数据平台项目时,就碰到了我说的选型问题。在做了非常细致的思考之后,他决定用 Go 做 Pandora。这对我来说是一个意料之外的决策。因为我自己在这个事情上并没有倾向性,而陈超我觉得他很可能还是会优先选 Scala。就在最近(国庆节前)某次聊天中,陈超回顾起这件事,总结了一下他为什么选择了 Go:极低的学习成本,极低的心智负担。如果用 Scala,新人入职要培训,还要担心写出糟糕的 Scala 代码。但是用 Go 新人不培训直接上岗,几次 Code Review 完后基本就能够知道怎么写出质量不错的 Go 代码了。

十年过去,Go 已经不再是一门小众语言。越来越多人在用 Go,喜欢上 Go。不记得是什么时候了,但是某一天通过 Google Trends 搜索 golang 发现全世界 Go 最火的地区是在中国时,那一刻真的很开心。

下一个十年会怎样?我知道有一些人很期望 Go 语言特性的迭代。但是如果你抱有这种想法可能会失望,因为下一个十年 Go 不会发生太大的变化。对远期需求变化的预测和把控能力,是 Go 的最大魅力之一。这一点上能够和 Go 相比的是 C 语言(C 语言不同版本的规范差异极少),但因为 Go 要解决的问题更多,做到这一点实际上也更难。下一个十年 Go 仍然会继续深耕服务端开发的生态,同时积极探索其他潜在的应用市场。

 

 
谋胆并重
相关实践学习
简单用户画像分析
本场景主要介绍基于海量日志数据进行简单用户画像分析为背景,如何通过使用DataWorks完成数据采集 、加工数据、配置数据质量监控和数据可视化展现等任务。
SaaS 模式云数据仓库必修课
本课程由阿里云开发者社区和阿里云大数据团队共同出品,是SaaS模式云原生数据仓库领导者MaxCompute核心课程。本课程由阿里云资深产品和技术专家们从概念到方法,从场景到实践,体系化的将阿里巴巴飞天大数据平台10多年的经过验证的方法与实践深入浅出的讲给开发者们。帮助大数据开发者快速了解并掌握SaaS模式的云原生的数据仓库,助力开发者学习了解先进的技术栈,并能在实际业务中敏捷的进行大数据分析,赋能企业业务。 通过本课程可以了解SaaS模式云原生数据仓库领导者MaxCompute核心功能及典型适用场景,可应用MaxCompute实现数仓搭建,快速进行大数据分析。适合大数据工程师、大数据分析师 大量数据需要处理、存储和管理,需要搭建数据仓库?学它! 没有足够人员和经验来运维大数据平台,不想自建IDC买机器,需要免运维的大数据平台?会SQL就等于会大数据?学它! 想知道大数据用得对不对,想用更少的钱得到持续演进的数仓能力?获得极致弹性的计算资源和更好的性能,以及持续保护数据安全的生产环境?学它! 想要获得灵活的分析能力,快速洞察数据规律特征?想要兼得数据湖的灵活性与数据仓库的成长性?学它! 出品人:阿里云大数据产品及研发团队专家 产品 MaxCompute 官网 https://www.aliyun.com/product/odps 
目录
相关文章
|
3天前
|
开发框架 安全 中间件
Go语言开发小技巧&易错点100例(十二)
Go语言开发小技巧&易错点100例(十二)
19 1
|
1天前
|
Go 开发者
Go语言函数的高级特性探索
【2月更文挑战第3天】本文旨在深入解析Go语言中函数的高级特性,包括可变参数函数、函数作为值传递、函数作为参数传递、函数作为返回值、函数指针以及泛型函数等。通过掌握这些高级特性,你将能够编写更加灵活和强大的Go语言程序。
|
1天前
|
Go
Go语言函数调用的深入探索
【2月更文挑战第3天】本文将对Go语言中的函数调用进行深入探讨,包括函数调用的基本语法、参数传递方式、返回值处理、延迟执行以及并发执行等方面。通过本文,读者将能够全面理解并掌握Go语言中函数调用的相关知识和技巧。
|
1天前
|
Go
Go语言函数定义详解
【2月更文挑战第3天】本文旨在深入探讨Go语言中函数的定义方法、语法规则以及相关的特性。我们将从基础开始,逐步解析函数的命名、参数、返回值以及匿名函数等核心概念,帮助读者建立起对Go语言函数定义的完整理解。
|
1天前
|
安全 Java 编译器
Go语言面试宝典:50道必会题目与精解
本文提供了50道覆盖Go语言核心概念、并发编程、内存管理、包管理、错误处理和测试等方面的面试题及其详细答案,旨在帮助开发者全面准备Go语言技术面试。
|
2天前
|
Java 编译器 Go
Go语言环境搭建
Go语言环境搭建
|
2天前
|
安全 Go API
Go语言的一些基本常识
Go语言的一些基本常识
|
2天前
|
程序员 Go 开发者
Go语言中的跳转控制结构:`goto`、`break` 和 `continue`
【2月更文挑战第2天】在Go语言中,跳转控制结构允许程序员直接控制程序的执行流程,通过`goto`、`break`和`continue`关键字实现代码的跳转、退出循环或跳过循环的某次迭代。本文将深入探讨这些跳转控制结构的使用场景、注意事项以及最佳实践,帮助读者更好地理解和应用Go语言中的跳转控制结构。
|
2天前
|
Go 开发者 索引
Go语言中的循环控制结构解析
【2月更文挑战第2天】本文将详细探讨Go语言中的循环控制结构,包括`for`循环、`range`循环以及`无限循环`的使用方法和适用场景。通过掌握这些循环结构,Go语言开发者能够更加高效地进行迭代操作、处理集合数据以及实现复杂的控制逻辑。
|
2天前
|
Go
Go语言中的条件控制结构详解
【2月更文挑战第2天】本文深入探讨了Go语言中的条件控制结构,包括`if`语句、`switch`语句以及它们的特点、使用场景和最佳实践。通过理解这些结构,读者可以更好地掌握Go语言中的条件判断和流程控制,从而编写出高效、清晰和可维护的代码。

相关产品

  • 云迁移中心