[译]Go语言中那些你未曾听说过的惊人优点
2018-02-12 Go中国
在过去的几年里你可能多次听到 Go 这门编程语言。尽管它的历史能够追溯到 2009 年,但是在最近的几年它的人气才开始飙升。
这篇文章并不介绍 Go 语言中那几个你经常看到的卖点。
相反,我将向你展示 Go 里面那些微小但意义非凡的特性,这些特性只有你在决定尝试 Go 之后才能了解到。
这些令人惊叹的特性在表面上看毫不起眼,但却能实实在在得帮你节省数周或者数月的工作量,让开发者更多地享受到软件开发的乐趣。
如果你是一个 Go 语言的新手,也请不用担心,这篇文章不需要任何与 Go 相关的语言知识。同时我也在文章的底部添加了几个链接,以便让你学习更多的内容。
接下来我们将会阅读到以下几个主题:
GoDoc
静态代码分析
内置的测试和性能分析框架
竞态条件检测
学习曲线
反射
偏执
文化
请注意,上面的列表并不遵循任何特定的顺序。
GoDoc
Go 非常重视代码中的文档,所以编写Go语言项目的文档非常简单。
GoDoc 是一个静态代码分析工具,可以直接通过你的代码生成美观的文档页面。GoDoc 一个卓越的地方在于,你不需要在代码中像 JavaDoc、PHPDoc 或者 JSDoc 那样使用额外的语法来构建注释,一切都是英文。
它通过在代码中获取尽可能多的信息,然后来构建大纲、结构以及对文档做格式化。它也具有所有花里胡哨的功能,例如交叉引用、示例代码等,而且能够直接链接到你的版本控制系统的仓库里。
所有你能做的就是添加一个优质的注释,例如// MyFunc transforms Foo into Bar,它们将会被引用到文档里。你甚至能够添加示例代码,然后在Web接口或者本地运行。
GoDoc 是整个 Go 社区唯一使用的文档引擎。这意味着所有 Go 编写的库或者应用程序都拥有相同文档格式。从长远来看,浏览这些文档时可以节省大量的时间。
这里有个例子,我最近的宠物项目的 GoDoc 页面:pullkee—GoDoc.
静态代码分析
Go 非常依赖静态代码分析。包括用于文档的 godoc、代码格式化的 gofmt、代码风格标记的 golint,还有其他更多的例子。
有个叫做 gometalinter 的项目,将上面提到的这类程序组合成一个单独的工具。
这些工具大多都实现为独立的命令行应用程序,并且能够很容易得与任何开发环境整合在一起。
静态代码分析实际上并不是现代编程的新东西,但 Go 将它更进一步。我无法估计它为我节省了多少时间。同时,它也能给你安全感,就如同有人在背后做你的后盾。
创造你自己的分析器也很简单,Go 内置了专用的包用来分析和使用 Go 源码。
你可以在这个 talk 中学到更多: GothamGo Kickoff Meetup: Go静态分析工具 by Alan Donovan.
内置的测试和性能分析框架
你有没有试过为从零开始的 Javascript 项目选择一个测试框架?如果有的话,可能就理解选择是多么令人纠结了。你也许已经意识到,你所选择的框架80%的功能你都不会用到。
当你需要做一些可靠性分析的时候,这个问题会再次出现在你面前。
Go 提供了一个内置的测试工具,旨在简化使用流程和提高工作效率。它尽可能为您提供了最简单的 API,并做出了最小的假设。你可以用它做各种类型的测试、性能分析,甚至提供可以运行的代码例子。
它默认提供对 CI 友好的输出,并且通常情况下只需要简单得使用 go test 运行即可。当然,它也支持并行测试、跳过标记以及其他更多的高级特性。
竞态条件检测
你可能了解过 Goroutines,它用来在 Go 中实现代码的并发执行。如果你还没了解过,这里有一个非常简短的解释。
无论使用哪种特定的技术,在复杂的程序中进行并发编程从来都不是一件容易的事,部分原因就在于可能存在的竟态条件。
简单来说,当多个并发操作以不可预知的顺序执行时,竟态条件就会发生,这可能会导致许多难以追踪的 bug。有没有花掉一整天的时间,去调试一个只能执行80%的集成测试的经历?这很有可能就是竟态条件引起的。
正因为如此,在 Go 里面并发编程是被严肃对待的一件事。Go 的工具链里面集成了一个强有力的工具,我们可以用它来捕获那些竟态条件。
你可以从这里了解更多以及学习如何使用它:Go竟态条件介绍—The Go Blog
学习曲线
我可以负责任得说,你只用一个晚上的时间就能学习完Go的所有语言特性。当然,还需要学习标准库、在不同特定领域中的最佳实践等,但两个小时完全足够你充满自信得编写一个HTTP服务,或者一个命令行程序。
官方提供了一份绝佳的文档,并且大部分高级主题也在它们的博客中有过介绍
将 Go 引入你的团队中要比 Java 系列、JavaScript、Ruby、Python、甚至 PHP 容易得多。开发环境很容易搭建,在正式代码编写之前你需要做的事少了很多。
反射
代码反射本质上是一种能力,可以让你获得各种不同的关于语言结构的元信息,比如变量和函数。
由于 Go 是一门静态语言,所以当涉及到更为送散的抽象编程时会受到一系列限制,尤其是和 Javascripth 或者 Python 比较时。
此外,由于 Go 没有关于泛型的概念,使用多类型的抽象方式进行编码时会受到更多挑战。然而也有许多人认为,相比于因为引入泛型导致语言复杂性增加,暂时舍弃泛型对语言会更有益。我完全同意。
根据 Go 的哲学(这是另外一个独立的话题),你应该尽量不要对你的解决方案进行过度设计。这也适用于动态语言。尽可能得使用静态类型,并且当你知道确切的类型时则使用接口。在 Go 中接口无处不在并且非常强大。
然而,在有些情况下你无法确定正在面对哪些数据。一个典型的例子是 JSON,您需要在应用程序中来回转换所有类型的数据,字符串,缓冲区,各种数字,嵌套结构等等。
为了避免这一切,你需要一个工具用来检查所有运行中的数据,然后根据其不同的类型和结构采取不同的行为。这个工具就是反射,Go 拥有一个优秀的反射包,用来让你的代码像 Javascript 一样动态运行。
但是也有一个警告:你必须知道反射的代价——只有在没有更加简单的方法时才使用它。
你可以在JSON源码包中阅读更多实际的代码:src/encoding/json/encode.go—Source Code
偏执
在使用 Javascript 时,确定规范和工具是我面对的最艰巨的问题之一。代码风格应该是怎样的?应该使用哪个测试库?要如何定义结构?应该依靠什么样的编程模式和方法?
这些确实会卡住我的进度,并且替代我本应该做的编码工作和满足用户的需求。
要声明一点的是,我了解这些约定都是为了你和你的团队。但是无论如何,即使是一群经验丰富的 Javascript 开发人员,也很容易发现他们在工具和范例上的绝大部分经验都不相同,但是从这些工具和经验获得的结果却是一致的。
很显然,这让团队协作变得更加困难,不论是分析问题还是在整合工作上。
Go 在这方面是与众不同的。所有人都必须遵循相同的风格、使用同一个内置在基本工具链中的测试框架。不过你可能有很多自己的见解,比如如何构造和维护代码、如何选择名称、应该遵循那种构造模式、如何让并发更有效等等。
虽然看起来有诸多限制,但是却能够帮你和团队节省大量的时间。在某些限制之下进行编码实际上是一件很好的事,在构建新代码和审理已有代码时都能够给予你最直接的帮助。
当然,这也导致了大部分Go项目看起来都非常相似。
文化
人们经常说:当你学习一门新的口语时,也在受到使用这门语言背后人们文化的影响。因此你所学的语言越多,你能体验到的人类差异性也就越多。
对于编程语言来说也是类似的。不管你未来如何使用一门新的编程语言,它总能带给你一些关于编程的新视角,或者某些特定的技术。
无论是函数式编程,模式匹配还是原型继承,一旦你学习了它,作为一名软件开发者,在解决问题时就多了一个能够使用的工具,并且能够改变你看待高质量编程的方式。
在这方面 Go 可以说是一个不错的投资。Go 最主要的文化就是保持简单、接地气的代码,不产生其他冗余的抽象并将可维护性放置在第一位。同时,人们应该将大多数时间花费在代码上面,而不是纠结在各种工具和环境上面的选择和维护上。
Go 的所有哲学都透露出一个相同的东西:最好只有一种做事的方式。
需要简单说明一点的是,当你需要构建相对比较复杂的抽象时,Go 也是可以支持的。这也是用简单换来的权衡。
如果你真的需要写很多关系复杂的抽象代码,使用像 Java 或者 Python 这样的语言会更适合,然而有这种需求的场景真的很罕见。
永远使用最合适的那个工具来工作。
总结
你可能之前没听说过 Go,或者一直将 Go 排除在关注范围外。不管怎样,当你或者你的团队开始新的项目或者打算改进已有的项目时,Go 会是一个非常优质的选择。
这篇文章并没有包含 Go 所有令人惊叹的特性,而只包含那些被低估的部分。
请尝试一下 Go,这会是一个令人难以置信的开始
如果你希望学习更多Go的好处,可以查看下面这些链接:
为什么你应该学习Go?—Keval Patel—Medium
告别Node.js—TJ Holowaychuk—Medium
即使你没有专门寻找一种新的语言,花一两个小时的时间学习也是值得的。也许在未来某一天会变得非常有用。
永远为你的手艺选择最称手的工具。
可点击“阅读原文”查看原文
阅读原文