你好,我是白明(英文名:Tony Bai),欢迎你和我一起学习 Go 语言。
我现在在一家初创企业东软睿驰工作,是一名车联网平台的架构师,同时我也是技术博客 tonybai.com 的博主、GopherChina 大会讲师。
从 2011 年开始我便关注了 Go 语言,是 Go 语言在国内的早期接纳者。那个时候,离 Go 开源还不过两年,没有人想到它会成长到今天这样,成为后端开发的主流语言之一。
在对 Go 长达十年的跟随和研究中,我沉淀了很多个人的经验和思考。我也希望通过这门课,跟你分享我学习和使用 Go 语言的一些心法。
我与 Go 的这十年
2011 年,一次偶然的机会,我非常幸运地看到了 Go 语言之父 Rob Pike 的 Go 语言课程幻灯片。当时我正经受着 C 语言内存管理、线程调度和跨平台运行等问题的折磨,看到 Go 语言的语法清新简洁,还支持内存垃圾回收、原生支持并发,便一见钟情。 我是个对编程语言非常“挑剔”的人,这跟我从事的方向有关。十多年来,我一直在电信领域从事高并发、高性能、大容量的网关类平台服务端的开发,这两年也进入了智能网联汽车行业。由于长期从事后端服务开发,我涉猎过很多后端编程语言。
我曾深入研究过 C++,短暂研究过 Java、Ruby、Erlang、Haskell 与 Common Lisp,但都因为复杂度、耗资源、性能不够、不适用于大规模生产等种种原因放弃了。
而且,如果你对我所在的行业有所了解,你可能会知道,我参与开发的系统对性能十分敏感。我也曾长期使用 C 语言作为生产语言,同时使用 Python 开发各种辅助工具。但是,C 语言的生产效率不高,各种陷阱也很多,而 Python 开发效率确实很高,但性能又不好。
难道就没有一门相对“完美”、符合我使用需求的编程语言吗?这个时候,Go 来了。
但在我开始接触和学习 Go 的 2011 年,Go 语言还未发布 Go 1.0 稳定版本,还处于“周发布(weekly release)”的状态。我还记得我接触的第一个 Go 版本还是release.r60,也就比 Rob Pike 的 Go 课程里使用的版本稍新一些。 但这个时候的 Go 版本,存在着很多不尽如人意的地方,尤其是 GC 延迟比较大,成为了 Go 语言上生产环境的最大障碍。
虽然 Go 早期版本无法上生产环境,但我却一直紧跟 Go 语言的演化进程。
从Go 1.4 版本开始,每当 Go 发布一个大版本,我都撰文分析这个大版本中 Go 语言的主要变化。这一系列文章至今仍在继续,未来也将持续进行下去。 特别是在 Go 1.5 版本实现自举、Go 1.11 版本解决 Go 包依赖问题后,Go 语言逐渐成熟,我也逐渐尝试在生产中使用 Go。从开始替代 Python 编写一些辅助工具,到编写一些网关所需的网络协议,我发现 Go 都可以完美适用。
一直到近些年,Go 替代了 C、Python,成为了我的第一生产语言。我开始直接使用 Go 编写生产系统,诸如短信网关、5G 消息网关、MQTT 网关,还有 API 网关等等。事实证明,Go 语言不仅生产效率高,其应用的执行效率也完全能满足要求。
从 2019 年开始,我将自己每天阅读到的 Go 社区的优秀技术资料整理成公开的Gopher 日报供大家参阅。在国内 Go 社区中,Gopher 日报得到了圈里许多同学的欢迎。 紧跟 Go 演进十年的我,已经将 Go 语言的点点滴滴深深地烙印在大脑中。
推荐你入坑 Go 的三大理由
如果说十年前的我是因为“一见钟情”瞬间入坑 Go,那么在十年后的今天,我们应该做的是系统地、认真地思考一下为什么要选择学习 Go。
我想了想,我会从这三个角度建议你现在开始学习 Go 语言。
第一个理由:对初学者足够友善,能够快速上手。
十多年来,业界都公认:Go 是一种非常简单的语言。到底有多简单呢?在 2011 年,我从一个 C 语言程序员的身份开始学习 Go,使用 Rob Pike 的 Go 教程,我在一天之内就学完了 Go 的全部语法,一周内就可以编写一些简单、实用,而且质量不低的小程序了。
而且,跟现在很多逐渐添加各种特性的语言相比,Go 不仅一开始简单,直到现在也都保持“简单”。Go 的设计者们在发布 Go 1.0 版本和兼容性规范后,似乎就把主要精力放在精心打磨 Go 的实现、改进语言周边工具链,还有提升 Go 开发者体验上了。演化了十多年,Go 新增的语言特性也同样是“屈指可数”。
正因为如此,作为静态编程语言的 Go 已经将入门门槛,降低到和动态语言一个水平线上了。
第二个理由:生产力与性能的最佳结合。
Go 的简单和对初学者的友善可以让更多的开发者走进 Go 语言大门,但要让更多开发者留在 Go 语言世界,Go 还需体现出自己的核心竞争力。这个核心竞争力就是,Go 语言是生产力与性能的最佳结合。
如果你熟悉的是静态语言,那你刚好就是 Go 最初的目标用户。Go 创建的最初目的,就是构建流行的、高性能的服务器端编程语言,用以替代当时在这个领域使用较多的 Java 和 C++。而且,Go 也实现了它的这个目标。
Go 语言的性能在带有 GC 和运行时的语言中名列前茅,与不带 GC 的静态编程语言(比如 C/C++)之间也没有数量级的差距。在各大基准测试网站上,在相同的资源消耗水平的前提下,Go 的性能虽然低于 C++,但高出 Java 不少。
如果你熟悉的是动态语言,那也完全不用担心。Go 的大部分早期采用者,就来自动态语言程序员群体,包括 Python、JavaScript、Ruby 和 PHP 等语言的使用群体。因为和动态语言相比,Go 能够在保持生产力的同时,大幅度提高性能。比如,全球知名的非营利教育组织可汗学院从 2019 年末开始,就将其在线教育平台的实现从 Python 迁移到了 Go。虽然 Go 代码行数要多于 Python,但他们收获了近 10 倍的性能提升。 如果你立志或者已经上手云开发,那你就更应该马上开始学习 Go 语言。现在,Go 已经成为了云基础架构语言,它在云原生基础设施、中间件与云服务领域大放异彩。同时,GO 在 DevOps/SRE、区块链、命令行交互程序(CLI)、Web 服务,还有数据处理等方面也有大量拥趸,我们甚至可以看到 Go 在微控制器、机器人、游戏领域也有广泛应用。
第三个理由:快乐又有“钱景”。
Go 最初的目标,就是重新为开发人员带来快乐。这个快乐来自哪里呢?相比 C/C++,甚至是 Java 来说,Go 在开发体验上的确有很大提升。笼统来说,这个提升来自于简单的语法、得心应手的工具链、丰富和健壮的标准库,还有生产力与性能的完美结合、免除内存管理的心智负担,对并发设计的原生支持等等。而这些良好的体验,恰恰是你写 Go 代码时的快乐源泉。
当然了,我相信你学习和使用 Go 肯定不是为了自嗨。运用 Go 体现自身价值,赢得理想职位才是最终目标。在十年后的今天,无论是在国内还是国外,无论是在大厂还是初创小公司,Go 都有着广泛的应用。Go 语言人才越来越抢手,对他们的争夺也日益激烈。
有报告表明,在腾讯、字节跳动、Uber 等许多公司,Go 都是极其受欢迎,在字节跳动、Uber 内部甚至已经成长为主力语言。
这还仅仅是以欧美开发人员调查数据为主的计算结果。在 Go 更加火爆的国内,Go 的平均薪水水平位次可能还要更高。
怎样学才能少走弯路?
看到 Go 语言对初学者如此友好,又是生产力与性能结合得最好的语言,写起来还能体会到快乐。关键是当前国内外互联网大厂、初创小厂也都广泛接纳并应用 Go,就业“钱景”极佳!很多人都纷纷投身于 Go 语言的学习中,但是盲目的“一头热”只会让你多走许多弯路。
我总结了一下,最常见的无非就是这几个:
“入错行”,从开始到放弃。如果你在最开始缺乏对这门语言的认真评估,盲目投入进去,后期沉没的时间和精力成本都会巨大;
不动手。语言学习不是“纸上谈兵”,要动手去用,并且动手越早效果越好;
用其他编程语言思维编写 Go 代码。我认为,每门编程语言都有着自己独特的编程思维方式,如果你用其他编程语言的思维方式去写 Go 代码,那只能“形神皆丧”,无法掌握语言真谛;
没有建立起“设计意识”。编程语言学习的最终目的是写出具有现实实用意义的程序,所以你要培养自己选择适当的语言元素构造程序骨架的能力,也就是“设计意识”。尤其是要弄清楚不同语言元素所在的层次,不然你只能停留在“Hello, World”的世界里。
那么,我们到底要怎么学才能学好 Go 呢?
学好 Go 的前提是能坚持学下去。而要保证持续学下去,做好 Go 入门学习就至关重要。入门学习就好比一座在建大厦的地基,只有地基坚实、稳固,大厦才可能迎来建成,并耸立云霄的那天。
那么如何做好入门学习呢?这里告诉你三个诀窍与五个阶段。所谓三个诀窍是“心定、手勤、脑勤”。什么意思呢?我将这个入门课的学习分为下面五个阶段,我会结合这五个阶段来和你说明这三个诀窍。
第一个阶段:前置篇,“心定”建立认同感。
这一部分,我会带你了解 Go 的前世今生和设计哲学。如果你是有其他语言编程经验的开发人员,你就更应该完成前置篇的学习了。
这一部分存在的意义就是让你“心定”。所谓“心定”就是为了建立对 Go 语言的认同感。这种认同感是全方位的,包括对 Go 语言的设计目标、设计哲学、演化思路,还有社区行为规范等等。只有“心定”,才能避免出现“Hello-and-Bye”的情况,这是学好 Go 的前提。
第二个阶段:入门篇,“手勤”多动手实践。
在这一部分中,我将告诉你在不同平台上安装各种 Go 版本的方法,带你了解一个 Go 程序应该长什么模样,看看一些实用 Go 程序都有哪些语法元素和结构。关于 Go 的版本,如果我在课程中没有特地说明,那便默认使用的是 Go 最新的稳定版本,这里请你注意下。
编程不是“纸上谈兵”。我们最终都是要将编写完的源码提交给计算机编译运行的,因此,我希望你在这部分多动手、多实践。我在入门篇中将会让你拥有“照猫画虎”的能力。只有拥有这种能力,你才能“随心所欲”地动手实践。
第三个阶段:基础篇,“脑勤”多理解,夯实基础。
这一部分,我们会围绕着“程序 = 数据 + 算法”的逻辑,从变量、常量等基本概念,到数据类型,再到广义的算法,让你可以用 Go 建立对现实世界的抽象认知,也能明白 Go 程序运行的基本逻辑。
在基础篇的结尾,我们会结合已学习的基础语法做一个小练习项目。实践与理论的结合才能达到更好的学习效果。
第四个阶段:核心篇,“脑勤 +”建立自己的 Go 应用设计意识。
在这部分,我会跟你介绍 Go 语言独有或经过较大创新的接口类型与 goroutine 等并发原语类型,这些语法元素是 Go 语言的核心。
Go 接口与 Goroutine 等并发原语类型有一个共同的特点,那就是它们都是可以影响到 Go 应用程序的结构设计的语法元素。Goroutine 等并发原语是 Go 应用运行时并发设计的基础,而接口则是 Go 推崇的面向组合设计的抓手,这一动一静共同构成了 Go 应用程序的骨架。通过这一部分,你就能建立自己的 Go 应用“设计意识”。
第五个阶段:实战篇,攻克 Go 开发的“最后一公里”。
编程就是要做到学以致用。在掌握了 Go 语言的基础语法、核心语法并建立起自己的“设计意识”后,我们就是时候应用这些 Go 语言的特性来解决实际问题了。
在这部分中,我们将通过一个实战的例子,展示如何做好学习与使用之间的衔接,帮助你走完“使用 Go 进行生产级开发”这“最后一公里”。
更具体的目录,我也放在了这里,你可以看一下:
在开篇词的最后,我想说,Go 是一门非常优秀的后端编程语言,它简单而不失表达力,兼具高生产力与战斗力(高性能)。它既能给你带去编码的快乐,也能因市场的广泛接受与热捧而提升你的个人价值。
所以,我衷心地希望你能完成这门课程的学习。希望我的这门课能帮助你将 Go 语言之路走得更顺畅,早日成长为一名优秀的 Go 语言开发工程师。
不要再犹豫了,来和我一起开启 Go 语言的学习之旅吧。