01|前世今生:你不得不了解的Go的历史和现状

你好,我是Tony Bai。

今天是我们的第一堂课。第一堂课的开场,我要做的事很简单,就想跟你聊一聊Go语言的前世今生。

我一直认为,当你开始接触一门新语言的时候,你一定要去了解它的历史和现状。因为这样,你才能建立起对这门语言的整体认知,了解它未来的走向。而且,也能建立你学习的“安全感”,相信它能够给你带来足够的价值和收益,更加坚定地学习下去。

所以,在这一节课,我就来跟你聊聊Go的前世今生,讲清楚Go到底是一门怎么样的语言,Go又是怎么诞生的,它经历了怎样的历史演进,它的现状和未来又会如何?

无论后面你是否会选择学习Go语言,无论你是否会真正成为一名Go程序员,我都建议你先了解一下这些内容,它会让你对编程语言的发展有更进一步的理解。

首先,我们就来看看Go语言是怎么诞生的,这可以让你真实地了解Go的诞生缘由、设计目标,以及它究竟要解决哪些问题。

Go语言是怎样诞生的?

Go语言的创始人有三位,分别是图灵奖获得者、C语法联合发明人、Unix之父肯·汤普森(Ken Thompson),Plan 9操作系统领导者、UTF-8编码的最初设计者罗伯·派克(Rob Pike),以及Java的HotSpot虚拟机和Chrome浏览器的JavaScript V8引擎的设计者之一罗伯特·格瑞史莫(Robert Griesemer)。

他们可能都没有想到,他们三个人在2007年9月20日下午的一次普通讨论,就这么成为了计算机编程语言领域的一次著名历史事件,开启了一个新编程语言的历史。

图片

那天下午,在谷歌山景城总部的那间办公室里,罗伯·派克启动了一个C++工程的编译构建。按照以往的经验判断,这次构建大约需要一个小时。利用这段时间,罗伯·派克和罗伯特·格瑞史莫、肯·汤普森坐在一处,交换了关于设计一门新编程语言的想法。

之所以有这种想法,是因为当时的谷歌内部主要使用C++语言构建各种系统,但C++的巨大复杂性、编译构建速度慢以及在编写服务端程序时对并发支持的不足,让三位大佬觉得十分不便,他们就想着设计一门新的语言。在他们的初步构想中,这门新语言应该是能够给程序员带来快乐、匹配未来硬件发展趋势并适合用来开发谷歌内部大规模网络服务程序的。

趁热打铁!在第一天的简短讨论后,第二天这三位大佬又在谷歌总部的“雅温得(Yaounde)”会议室里具体讨论了这门新语言的设计。会后罗伯特·格瑞史莫发出了一封题为“prog lang discussion”的电邮,对这门新编程语言的功能特性做了初步的归纳总结:

图片

这封电邮对这门新编程语言的功能特性做了归纳总结。主要思路是,在C语言的基础上,修正一些明显的缺陷,删除一些被诟病较多的特性,增加一些缺失的功能,比如,使用import替代include、去掉宏、增加垃圾回收、支持接口等。这封电邮成为了这门新语言的第一版特性设计稿,三位大佬在这门语言的一些基础语法特性上达成了初步一致。

9月25日,罗伯·派克在一封回复电邮中把这门新编程语言命名为“go”:

图片

在罗伯·派克的心目中,“go”这个单词短小、容易输入并且在组合其他字母后便可以用来命名Go相关的工具,比如编译器(goc)、汇编器(goa)、链接器(gol)等(go的早期版本曾如此命名go工具链,但后续版本撤销了这种命名方式,仅保留go这一统一的工具链名称 )。

这里我还想澄清一个误区,很多Go语言初学者经常称这门语言为Golang,其实这是不对的:“Golang”仅应用于命名Go语言官方网站,而且当时没有用go.com纯粹是这个域名被占用了而已。

从“三人行”到“众人拾柴”

经过早期讨论,Go语言的三位作者在语言设计上达成初步一致后,便开启了Go语言迭代设计和实现的过程。

2008年初,Unix之父肯·汤普森实现了第一版Go编译器,用于验证之前的设计。这个编译器先将Go代码转换为C代码,再由C编译器编译成二进制文件。

到2008年年中,Go的第一版设计就基本结束了。这时,同样在谷歌工作的伊恩·泰勒(Ian Lance Taylor)为Go语言实现了一个gcc的前端,这也是Go语言的第二个编译器。

伊恩·泰勒的这一成果不仅仅是一种鼓励,也证明了Go这一新语言的可行性 。有了语言的第二个实现,对Go的语言规范和标准库的建立也是很重要的。随后,伊恩·泰勒以团队的第四位成员的身份正式加入Go语言开发团队,后面也成为了Go语言,以及其工具设计和实现的核心人物之一。

罗斯·考克斯(Russ Cox)是Go核心开发团队的第五位成员,也是在2008年加入的。进入团队后,罗斯·考克斯利用函数类型是“一等公民”,而且它也可以拥有自己的方法这个特性巧妙设计出了 http 包的 HandlerFunc 类型。这样,我们通过显式转型就可以让一个普通函数成为满足 http.Handler接口 的类型了。

不仅如此,罗斯·考克斯还在当时设计的基础上提出了一些更泛化的想法,比如 io.Readerio.Writer 接口,这就奠定了Go语言的I/O结构模型。后来,罗斯·考克斯成为Go核心技术团队的负责人,推动Go语言的持续演化。

到这里,Go语言最初的核心团队形成,Go语言迈上了稳定演化的道路。

2009年10月30日,罗伯·派克在 Google Techtalk 上做了一次有关Go语言的演讲“The Go Programming Language”,这也是Go语言第一次公之于众。十天后,也就是2009年11月10日,谷歌官方宣布Go语言项目开源,之后这一天也被Go官方确定为Go语言的诞生日。

图片

在Go语言项目开源后,Go语言也迎来了自己的“吉祥物”,是一只由罗伯·派克夫人芮妮·弗伦奇(Renee French)设计的地鼠,从此地鼠(gopher)也就成为了世界各地Go程序员的象征,Go程序员也被昵称为Gopher,在后面的课程中,我会直接使用Gopher指代Go语言开发者。

图片

Go语言项目的开源使得Go语言吸引了全世界开发者的目光,再加上Go三位作者在业界的影响力以及谷歌这座大树的加持,更多有才华的程序员加入到Go核心开发团队中,更多贡献者开始为Go语言项目添砖加瓦。于是,Go在宣布开源的当年,也就是2009年,就成为了著名编程语言排行榜TIOBE的年度最佳编程语言。

2012年3月28日,Go 1.0版本正式发布,同时Go官方发布了“Go 1兼容性”承诺:只要符合Go 1语言规范的源代码,Go编译器将保证向后兼容(backwards compatible),也就是说我们使用新版编译器也可以正确编译用老版本语法编写的代码

图片

从此,Go语言发展得非常迅猛。从正式开源到现在,十一年的时间过去了,Go语言发布了多个大版本更新,逐渐成熟。这里,我也梳理了迄今为止Go语言的重大版本更新,希望能帮助你快速了解Go语言的演化历史。

图片

Go是否值得我们学习?

时间已经来到了2021年。经过了十余年的打磨与优化,如今的Go语言已经逐渐成为了云计算时代基础设施的编程语言。你能想到的现代云计算基础设施软件的大部分流行和可靠的作品,都是用Go编写的,比如:Docker、Kubernetes、Prometheus、Ethereum(以太坊)、Istio、CockroachDB、InfluxDB、Terraform、Etcd、Consul等等。当然,这个列表还在持续增加,可见Go语言的影响力已经十分强大。

Go除了在云计算基础设施领域,拥有上面这些杀手级应用之外,Go语言的用户数量也在近几年快速增加。Go语言项目技术负责人罗斯·考克斯甚至还专门写过一篇文章,来估算全世界范围的Gopher数量。按照他的估算结果,全世界范围的Gopher数量从2017年年中的最多100万,增长到2019年11月的最多196万,大概两年半翻了一番。庞大的Gopher基数为Go未来的发展提供持续的增长潜力和更大的想象空间。

那么Go语言前景究竟如何,值不值得投入去学习呢?

我在想,是否存在一种成熟的方法,能相对客观地描绘出Go语言的历史发展趋势,并对未来Go的走势做出指导呢?我想来想去,觉得Gartner的技术成熟度曲线(The Hype Cycle)可以借来一试。

Gartner的技术成熟度曲线又叫技术循环曲线,是企业用来评估新科技是否要采用或采用时机的一种可视化方法,它利用时间轴与该技术在市面上的可见度(媒体曝光度)决定要不要采用,以及什么时候采用这种新科技,下面就是一条典型的技术成熟度曲线的形状:

同理,如果我们将这条技术成熟度曲线应用于某种编程语言,比如Go,我们就可以用它来判断这门编程语言所处的成熟阶段,来辅助我们决定要不要采用,以及何时采用这门语言。

我们从知名的TIOBE编程语言指数排行榜获取Go从2009年开源以来至今的指数曲线图,并且根据Go版本发布历史在图中标记出了各个时段的Go发布版本,你可以看看。

图片

对比前面的Gartner成熟度曲线,我们可以得出这样的结论:Go在经历了一个漫长的技术萌芽期后,从实现自举的Go 1.5版本开始逐步进入“期望膨胀期”,在经历从Go 1.6到Go 1.9版本的发布后,业界对Go的期望达到了峰值。

但随后“泡沫破裂”,在Go 1.11发布前跌到了“泡沫破裂期”的谷底,Go 1.11版本引入了Go module,给社区解决Go包依赖问题注射了一支强心剂,于是Go又开始了缓慢爬升。

从TIOBE提供的曲线来看,Go 1.12到Go 1.15版本的发布让我们有信心认为Go已经走出“泡沫破裂谷底期”,进入到“稳步爬升的光明期”。

至于Go什么时候能达到实质生产高峰期呢?

我们还不好预测,但这应该是一个确定性事件。我认为现在离它到达实质生产高峰期只是一个时间问题了。也许预计在2022年初发布的支持Go泛型特性的Go 1.18版本,会是继Go 1.5版本之后又一“爆款”,很可能会快速推动Go迈入更高的发展阶段。

小结

到这里,我们今天这节课就结束了。在这一节课里,我们一起探讨了“Go从哪里来,并可能要往哪里去”的问题。

我前面也说了,一门编程语言的历史和现状,能给你带来学习的“安全感”,相信它可以提升你的个人价值,也会让你获得丰厚的回报。你也会更加清楚地认识到:自己为什么要学习它?它未来的发展趋势又是怎样的?而且,当这门语言的现状能给予你极大“安全感”的时候,我们才会“死心塌地”地学习和钻研这门语言,而不会有太多的后顾之忧。

从Go本身的发展来看,和多数编程语言一样,Go语言在诞生后,度过了一个较长的“技术萌芽期”。然后,实现了自举,而且对GC延迟进行了大幅优化的Go 1.5版本,成为了Go语言演化过程中的第一个“引爆点”,推动Go语言进入“技术膨胀期”。

也正是在这段时间内,Go语言以迅雷不及掩耳盗铃之势推出了以Docker、Kubernetes为典型代表的“杀手级应用”,充分展现了实力,在世界范围收获了百万粉丝,迸发出极高的潜力和持续的活力。

Go开源于2009年末,如果从那时算起,Go才11岁。但在Go核心开发团队眼中,Go的真正诞生年份是2007年,距今已13个年头有余了。

回顾一下计算机编程语言的历史,我们会发现,绝大多数主流编程语言,都将在其15至20年间大步前进。Java、Python、Ruby、JavaScript和许多其他编程语言都是这样。如今Go语言也马上进入自己的黄金5~10年,从前面的技术成熟度曲线分析也可以印证这一点:Go已经重新回到“稳步爬升的光明期”。

对于开发人员来说,Go语言学习的最佳时刻已经到来了

思考题

相较于传统的静态编译型编程语言(如C、C++),Go做出了哪些改进?你可以思考一下,欢迎在留言区留下你的答案。

感谢你和我一起学习,也欢迎你把这节课分享给更多对Go语言感兴趣的朋友。我是Tony Bai,我们下节课见。

精选留言

  • lesserror

    2021-10-13 22:09:24

    Tony Bai,你好。文章读完了,写的很好。关于文中有几点疑问,麻烦解答一下。

    1. “为 Go 语言实现了一个 gcc 的前端?” 怎么理解这个“前端”的意思。

    2. “这样,我们通过显式转型就可以让一个普通函数成为满足http.Handler接口的类型了。” 这里的“显示转型”该怎么理解呢?

    3. 能否解释一下“运行时”这个概念呢? 好多文章都是一笔带过,想知道到底是一个什么概念。

    作者回复

    这三个问题问的都非常棒👍

    这里是第一讲,因此很多技术术语可能没有更细致的解释,随着课程的展开,一些术语在后续的课程讲解中都会涉及到。

    既然提出这些问题了,我就来简单解答一下。

    第一个问题:什么是编译器的前端?在计算机专业编译原理课上大家可能都会学到一个编译器的完整编译过程包括:词法分析,语法分析,类型检查,中间代码生成,代码优化,目标代码生成,目标代码优化等几个阶段。从词法分析到中间代码生成,这就是编译器前端所要负责的事情。而代码优化和目标代码生成,则是编译器后端的职责。

    文中提到了实现了一个gcc的前端,就是实现了一个程序,这个程序可以读取go源码并通过词法分析、语法分析、类型检查,最终生成中间代码,而这个中间代码可以被gcc后端所识别并生成最终目标代码。

    第二个问题:什么是显式转型?这是一个语法层面的术语。举个简单例子,在Go中,如果一个变量的类型为int,但我要将其与另一个int64类型的变量进行加法运算,我们不能直接将它们相加,我们必须将它们显式的转换为同一类型后才能相加,这里的转换过程就简称为显式转型,这个例子转换为代码就是:

    var a int = 5
    var b int64 = 6
    c := int64(a) + b

    其中的int64(a)就是对变量a进行显式转型。

    第三个问题,什么是go运行时?

    go 运行时,也称为go runtime。

    它在那里?其本身就是每个go程序的一部分,它会跟你的源码一起编译并连接到目标程序中。即便你只是写了一个hello world程序,这个程序中也包含了runtime的实现。

    它在我的程序中具体负责什么?runtime负责实现go的垃圾收集、并发、内存堆栈管理以及Go语言的其他关键功能。

    它的代码在哪里?它大部分以标准库的形式存放在每个Go发布版的源码中。

    感谢对本专栏的支持!

    2021-10-14 12:49:54

  • aoe

    2021-10-14 09:45:50

    go有吉祥物,其他2个语言没有
  • 罗杰

    2021-10-14 12:31:18

    相比 C/C++ 每个平台的支持问题,Go 的表现简直好太多了。但有个问题,我疑惑了好长好长时间了,希望 Tony 老师解答:printf 能格式化字符串,换行就要手动添加 "\n",println 又不能格式化字符串。我想知道为什么要这样的设计?在看我来这就是特别反人类的设定,Rust 的 println!("{}", a); 才是符合直觉的。
    作者回复

    净给我出难题😝

    这个问题我是这么看的,printf是go提供的标准格式化io的函数,它能实现你所期望的所有功能。与c语言的printf是对等的。但println这个函数你可以看成是一种“语法糖”,它本身就是一个特例,你可以用go doc看看println的manual,println原语义就是使用一种默认的格式输出数据到stdout上。你认同这种默认格式,你就使用println,简化你的代码。否则,你就用printf就好了。

    2021-10-14 13:08:52

  • 文经

    2021-10-26 18:00:06

    我刚转到Go一个半月,之前主要做iOS开发。觉得App开发的天花板太低了,就坚决转型了。
    我看完《Go程序设计语言》和其它一些书,也上了极客时间的《Go训练营》。
    但是都没有很详细的提到Go的历史和现状,正如白老师所说,了解Go语言的前世今生能够对这门语言更有信心。很高兴今天加入这个专栏,赶上进度,跟着白老师好好学习。
    作者回复

    加油!

    2021-10-30 12:41:09

  • 麦芽糖

    2022-01-13 23:11:00

    Go 的但是是因为3个前辈在编译 C++ 的时候需要等待很久,在这段时间内他们交换了对一门新的语言的想法。

    有了想法,就有定义,于是他们开始设想 Go 的特性。如
    ● 编译速度提升
    ● 修复缺陷
    ● 摈弃C++不好的地方
    ● 补全想要的功能
    ● 并发能力

    为什么是 Go ?
    因为这个单词很简单。

    至于有人说 Golang,其实没有关系,Golang 仅仅是 Go 的官方网站,因为 go.com 被注册了。

    2008 年 Go 就诞生了,团队逐步扩大,2009 年开源,2009-11-10 被定为诞生日。
    Go 的吉祥物是地鼠,Go 程序员叫 Gopher。

    Go 能用在生产环境是有个节点 Go 1.5,这个版本解决了 Go 的 GC 回收问题。

    Go 的现状挺好的。
    现在的公司在用,而且公司的业务是对性能要求高的。
    前公司也是从 python 转型到 Go。
    而且之前的同事在转型到后台的时候也会选型 Go,也即是说会越来越多的公司在选择后端语言的时候会选择 Go。
    而且 Go 的程序员挺难招到的。
    我了解到 Docker 是用 Go 写的。
    从大数据来看一门语言的生命周期,也能看得出来在 5 年内 Go 会引来爆发期。
    云也倾向于 Go 语言。
    作者回复

    👍

    2022-01-30 13:36:23

  • 布凡

    2021-10-13 22:50:21

    dapr也是go编写
    作者回复

    是的,微软牵头推出的云原生分布式应用开发框架dapr的默认实现就是用的Go。

    2021-10-14 13:11:33

  • Jack

    2022-07-16 12:28:03

    老师怎么看待Go和Rust的比较?
    作者回复

    以前在微博上发过一个观点:让一个习惯了go编程的gopher去用rust,就好比开惯了自动挡汽车的司机去开手动挡,虽然能省些油,传动效率高,但换挡时机和换挡动作还得花很长时间去练习,这个前提还是这个司机之前拿的是C1驾照(C/C++出身)。

    2022-07-16 20:15:29

  • 重洋

    2021-10-26 12:54:59

    老师,作为JAVA语言开发者,如果想要研究k8s、云原生领域,go语言需要掌握到什么程度呢?
    作者回复

    Go入门后,就基本可以看懂大部分Go应用层源码。如果要研究k8s、docker等平台的原理,那么还有一些网络、存储等语言之外的东西需要学习。

    2021-10-26 15:54:16

  • 西红柿牛男

    2021-10-18 20:24:32

    go有计划加入机器学习库吗?
    作者回复

    机器学习目前python一家独大。其他语言包括go都在努力抢市场份额。go在机器学习方面的成果还不那么显著,但从几个go机器学习相关的开源项目的活跃度来看,go社区还在积极努力。可以看看像gonum、spago这样的项目。

    2021-10-21 07:00:58

  • Ali

    2022-11-21 10:04:34

    老师 Go目前企业比较流行的微服务框架有哪些
    作者回复

    我这类框架用的少,我了解的用的比较多的,包括:
    - https://github.com/go-kit/kit
    - https://github.com/go-micro/go-micro
    - https://github.com/go-kratos/kratos
    - https://github.com/zeromicro/go-zero
    等等吧。

    2022-11-21 15:59:26

  • 黄伟伟

    2023-01-28 14:48:12

    这个教程有对应源码吗
    作者回复

    有的,每篇最后一讲的实战课都会有完整源码在 https://github.com/bigwhite/publication/tree/master/column/timegeek/go-first-course。其他讲中的源码基本都是copy即可run的。

    2023-01-28 21:13:35

  • GAC·DU

    2021-10-14 11:28:43

    内存管理,Go协程,面向对象
  • 西米

    2021-10-13 17:39:06

    相比c和c++ ,go有了垃圾回收,更快的编译速度
  • Neo_Zhang

    2022-03-08 13:56:42

    刚大学毕业开始用Go做服务器开发,给我的第一感觉就是它的简洁和Python一样,同时保留了C语言的一些特性。
    作者回复

    👍

    2022-03-08 21:43:03

  • iMARS

    2022-11-02 10:18:51

    我一致期待把go语言引入应用开发中,我们是做企业级的管理系统,目前采用的技术栈有小部分的.net以及Java,但也常常被性能等问题所困扰,除了应用架构设计面的问题以外。我更细往可以借助go的轻量和特性,来提供整个研发效能及运行时的效能。但目前看,引入的困难在以下几点:1、go的开发者和社会资源还是太少 2、可被复用且被市场验证的企业级应用架构较少(除了K8s以外)。希望老师也能给一些建议,谢谢。
    作者回复

    1. 建议自己内部培养,go语言上手快。但组内最后有1-2个高手。
    2. 和java比,go企业级应用架构的确不多,没有像java spring那样的全家桶。但go社区有一种尽量不依赖框架的倾向。我这块也没有太好的建议。如果要依赖框架,可以尽量依赖国内外主流的,国内的go-zero,国外的go-micro等微服务应用框架。

    2022-11-02 16:33:52

  • 陈染

    2022-10-27 19:47:18

    相较于传统的静态编译型语言(C,C++),go做的改进:1. 复杂性降低;2.更快的编译速度;3.更好地支持并发
    作者回复

    👍

    2022-10-28 13:20:59

  • 天天向上

    2022-08-05 22:10:58

    Go语言大事记,白老师整理的非常清晰,是不是可以持续动态更新!
    作者回复

    好建议👍,后续和编辑老师商量一下。

    2022-08-08 18:14:39

  • co

    2022-02-08 12:47:59

    语法层面,做到很多简化:没有指针、宏,变量声明简化(背后是类型推导系统)等等。
    语义层面,并发模型优化。有了gc,比传统静态语言内存管理上抽象层次更高。
    作者回复

    👍

    2022-02-08 21:21:08

  • 张申傲

    2021-12-01 16:56:17

    听到老师的东北口音实在太亲切了,哈哈哈~ 十分认同老师对 Go 语言前景的展望,希望老师推荐几本 Go 语言的书籍作为课程之外的补充。
    作者回复

    👍 在后面的加餐中有关于参考书籍的介绍。

    2021-12-15 16:03:08

  • 春是春天的春

    2021-10-25 08:35:07

    易上手、编译构建简单、支持并发的场景