犯错是每个人生活的一部分。正如爱因斯坦曾说过:一个从未犯过错的人从未尝试过新东西。
最重要的不是我们犯了多少错误,而是我们从错误中学到了多少东西。
这个观点同样适用于编程领域。
我们从一门编程语言中获取经验不是一个神奇的过程,它包含试错和从错误中学习的过程。
今天就和大家分享一本帮助我们从错误中学习编程语言的书——《100个Go语言典型错误》!
本书的目的是通过观察和学习人们在使用 Go 的过程中经常犯的 100 个错误来帮助读者成为一个更熟练的 Go 开发者。
有些人认为 Go 是一门简单的语言。从某种意义上看,这的确不能说是错的。因为一个新手可能花不到一天的时间就能掌握这门语言的主要特性。如果 Go 很简单,为什么还要专门读一本以错误概念为中心的书呢?
01 简单不意味着容易
简单和容易之间还是有一些不同的。简单,在技术中意味着学习或理解起来不复杂。而容易意味着我们不需要花太大成本就可以完成任何事情。Go 语言学起来简单,但是掌握起来不容易。
以并发为例,在 2019 年,一篇专注于并发错误的论文发布了——“Understanding Real-World Concurrency Bugs in Go”。这篇论文是第一篇对并发错误进行系统研究的文章。
文章中研究了多个用 Go 编写的代码库,比如,Docker、gRPC 和 Kubernetes。这篇文章最主要的观点之一是,尽管人们认为消息传递比共享内存更容易处理,但绝大多数阻塞问题都是由于错误使用channel 造成的。
对于这样的结论你有什么反应呢?是否会认为语言设计者使用消息传递的方式是错误的呢?是否应该重新考虑在项目中如何处理并发问题呢?并不是。
这并不是要在消息传递和共享内存之间决定谁是更优解的问题。而是我们作为 Go 开发者,应该深入了解如何使用并发,现代处理器对并发的影响,什么时候应该使用何种并发方案及如何避免出错。举这个例子是想说,尽管 goroutine 和channel 的概念学起来比较简单,但是在实践中并不简单。
这个主旨——简单不意味着容易,不仅仅是说并发,还可以推广到 Go 语言的方方面面。
因此,想要成为一个 Go 语言开发高手,我们需要花费时间、努力,通过从错误中学习来对这门语言的各个方面做深入了解。
本书的目标是通过深入研究 100 个 Go 语言错误来帮助读者加速掌握 Go 语言。
02 100 个 Go 语言错误
我们为什么需要读一本研究常见Go错误的书呢?为什么不通过一本普通研究Go中不同主题的书来加深我们对 Go 的理解呢?
在 2011 年的一篇研究文章中,神经科学家表明,大脑成长的最佳时间是在面对错误的时候。你经历过从错误中进行学习,在几个月甚至几年后遇到相似的场景时又回忆起当初的错误这样的事情吗?正如 Janet Metcalfe 在另一篇文章中介绍的那样:发生这种情况是因为错误有促进作用。主要是因为我们不仅可以记住错误,还可以记住错误发生的场景。这就是为什么从错误中学习如此高效的原因之一。
为了加强这种促进作用,本书尽可能地在每个错误中都加入示例。本书不仅会介绍理论,还会帮助大家更好地避免犯错。在明白了错误背后的原理之后会帮助大家做出更多明智的、深思熟虑的决定。
告诉我,我会忘记;教给我,我会记得;让我参与进去,我能学会。
——无名氏
本书列出了七种主要的错误,总体来说,错误包括:
-
bug
-
不必要的复杂性
-
可读性差
-
非最佳组织形式
-
API 对用户不友好
-
代码有待优化
-
效率低
我们会在后面的内容中依次介绍这些错误。
▎bug
第一种错误是最明显的软件 bug。2020 年,Synopsys 进行的一项研究表明,仅在美国,由于软件 bug 造成的损失就超过 2 万亿美元。
此外,bug 还可能酿成惨剧。比如,加拿大原子能有限公司(AECL)生产的放射治疗机Therac-25,由于竞态条件,机器给患者的辐射剂量比预期的高出百倍,导致三名患者死亡。
因此,软件 bug 不仅仅和钱相关。作为开发者,我们应该记住自己的工作是多么有影响力。
本书涵盖了大量会导致软件 bug 的情况,包括:数据竞争、泄漏、逻辑错误和其他缺陷。
尽管准确的测试是尽早发现这些 bug 的一种方法,但由于时间限制和复杂性等因素,我们有时候可能来不及写测试用例。因此,作为一个 Go 开发者,避免这些常见的错误是非常有必要的。
▎不必要的复杂性
下一种错误是不必要的复杂性。软件复杂性的一个重要来源基于这样一个事实:作为开发人员,我们会努力想象未来会增加什么特性——与其立即解决具体的问题,不如构建出能解决未来出现任何特性的设计。然而,这在大多数情况下弊大于利,因为这样会使代码库变得更加复杂、难以理解和推理。
回到 Go 语言,我们可以想到大量的例子:开发人员想要对未来的需求做抽象,使用接口或泛型。本书会讨论应该避免引入不必要的复杂性来破坏代码库的主题。
▎可读性差
另一种错误是可读性差。正如 Robert C. Martin 在他的书《代码整洁之道》中所写的那样:代码的阅读和编写的时间比例超过 10∶1.5。①我们大多数人都是在可读性不那么重要的独立项目中开始编程的。然而,现代程序员都是在具有时间维度的情况下进行编程的:要确保在几个月、几年甚至几十年后仍然可以使用和维护一个应用程序。
在用 Go 编程时,我们可能会犯很多影响可读性的错误。这些错误包括:代码嵌套、数据类型表示、某些情况下不使用命名的结果参数。通过本书,我们将学习为了读者(也包括未来的我们自己),如何写出可读性强的代码。
▎非最佳组织形式
无论是在新项目中,还是由于我们采取了不准确的方式,造成另一种错误使项目和代码不是最佳解法。这样的问题会让一个项目难以理解和维护。本书涵盖了 Go 中这类常见的错误。比如,我们将学习如何组织一个项目及如何处理公共函数包或初始化函数。总之,学习这些错误会帮助我们更高效地组织 Go 项目。
▎API 对用户不友好
另一种常见的错误是降低了 API 对客户端的便利性。如果一个 API 对用户不友好,那么它的表达能力就会降低,从而变得难以理解,也就容易使人犯错。
我们可以想到很多情况,比如过度使用 any 类型、使用错误的创建模式来处理可选项,或者盲目使用面向对象编程的标准实践,这些都会影响 API 的可用性。本书涵盖了阻碍我们给用户提供方便的 API 的常见错误。
▎代码有待优化
代码优化不足是开发者常犯的另一类错误。导致其发生的原因有很多,比如不了解语言特性,甚至是缺乏对语言的基本认知。性能是这种错误最明显的影响之一,但这种错误不仅仅是影响性能。
我们可以考虑为一些目标优化代码,如准确性。本书会提供一些常见的技术来确保浮点数计算的准确性,同时会涵盖大量的用例来说明代码优化不足造成的性能影响,比如并发度不够,不知道如何减少分配,或者数据对齐造成的影响。我们会通过不同的场景来解决待优化问题。
▎效率低
在大多数情况下,当我们在一个新项目上开发时,什么是最优的语言?最优的语言是使工作效率最高的语言。熟悉一门语言的工作方式并利用它达到最佳效果是提高效率的关键。
在本书中,我们会涉及很多场景和具体的例子来帮助我们在使用 Go 语言开发时提高工作效率。比如,我们会研究如何编写高效的测试来保证代码能正确运行,如何依赖标准库提高效率,如何充分利用分析工具和辅助工具。现在,是时候深入研究这 100 个常见的 Go 错误了。
Go 语言是一门现代编程语言,能提高开发者的工作效率,这对当今大多数公司而言是至关重要的。
Go 语言入门容易但精通难。这就是我们为什么需要深化对 Go 语言的认知,以便最有效地使用这门语言。
通过错误和具体例子进行学习是熟练掌握一门语言的有效方法。本书通过探讨 100 个常见的错误来加速我们对 Go 语言的掌握。
↑限时五折优惠↑