Go 语言实战 ( etc.) (Z-Library)
Statistics
3
Views
0
Downloads
0
Donations
Uploader

高宏飞

Shared on 2025年12月14日
Actions

Go 语言实战 ( etc.) (Z-Library)

技术

Author威廉·肯尼迪 (William Kennedy) / 布赖恩·克特森 (Brian Ketelsen) / 埃里克·圣马丁 (Erik St.Martin) [埃里克·圣马丁, 威廉·肯尼迪 / 布赖恩·克特森 /]

No description

ISBN: 7115445354
Publisher: 人民邮电出版社
Publish Year: 2017
Language: 中文
File Format: PDF
File Size: 10.0 MB
Support Statistics
¥.00 · 0times
Text Preview (First 20 pages)
Registered users can read the full content for free

Register as a Gaohf Library member to read the complete e-book online for free and enjoy a better reading experience.

“探索、学习并使用Go语言的简洁 而全面的指导手册。” ——摘自 Hugo 创立者 Steven Francia 为本书写的序 “这本权威的书为所有想要开始学习 Go语言的人提供了一站式的指引。” ——Sam Zaydel,RackTop Systems “写得太好了!完整介绍了Go语言。 强烈推荐。” ——Adam McKay,SUEZ “这本书把Go语言不寻常的部分讲 得通俗易懂。” ——Alex Vidal,Atlassian 的 HipChat 团队 Go语言实战 语 言 实 战 G o 分类建议:计算机/程序设计/Go语言 人民邮电出版社网址:www.ptpress.com.cn 美术编辑:董志桢 Go Go IN ACTION 即便不处理类似可扩展的Web 并发或者实时性能等复杂的系统 编程问题,应用程序开发也是一件非常困难的事情。尽管使用一些工 具和框架也可以解决这些常见的问题,但Go语言却以一种更加自然 且高效的方式正确处理了这类问题。由谷歌公司开发的Go语言,为 在基础设施中非常依赖高性能服务的初创公司和大企业提供了足够的 能力。 本书目标读者是已经有一定其他编程语言经验,想要开始学习 Go语言或者更深入了解Go 语言及其内部机制的中级开发者。本书 会提供一个专注、全面且符合习惯的视角。本书关注Go语言的规范 和实现,涉及的内容包括语法、Go的类型系统、并发、通道和测试 等主题。 本书主要内容 ●● Go 语言规范和实现。 ●● Go 语言的类型系统。 ●● Go 语言的数据结构的内部实现。 ●● 测试和基准测试。●● 本书假设读者是熟练使用其他语言(如 Java、Ruby、Python、 C# 或者 C++)的开发者。 William Kennedy 是一位熟练的软件开发者,也是博客GoingGo. Net 的作者。Brian Ketelsen 和Erik St. Martin 是全球Go 语言大会GopherCon的组织者,也是Go语言框架Skynet的联合作者。 语言实战 〔美〕●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●著 李兆海●●●译 谢孟军●●审校 ●William●Kennedy● Brian●Ketelsen● Erik●St.●Martin FM44535Go语言实战.indd 1-3 17-1-19 下午2:38
Go IN ACTION 语言实战 Go 人 民 邮 电 出 版 社 〔美〕 著 李兆海 译 谢孟军 审校 William Kennedy Brian Ketelsen Erik St. Martin FM44535Go语言实战.indd 4 17-1-19 下午2:36
 著 [美] William Kennedy Brian Ketelsen Erik St. Martin 译 李兆海 审 校 谢孟军 责任编辑 杨海玲 责任印制 焦志炜  人民邮电出版社出版发行 北京市丰台区成寿寺路 11 号 邮编 100164 电子邮件 315@ptpress.com.cn 网址 http://www.ptpress.com.cn 北京昌平百善印刷厂印刷  开本:8001000 1/16 印张:15.25 字数:326 千字 2017 年 3 月第 1 版 印数:1 – 4 000 册 2017 年 3 月北京第 1 次印刷 著作权合同登记号 图字:01-2015-8787 号 定价:59.00 元 读者服务热线:(010)81055410 印装质量热线:(010)81055316 反盗版热线:(010)81055315
译者序 Go 语言是由谷歌公司在 2007 年开始开发的一门语言,目的是能在多核心时代高效编写网络 应用程序。Go 语言的创始人 Robert Griesemer、Rob Pike 和 Ken Thompson 都是在计算机发展过程 中作出过重要贡献的人。自从 2009 年 11 月正式公开发布后,Go 语言迅速席卷了整个互联网后端 开发领域,其社区里不断涌现出类似 vitess、Docker、etcd、Consul 等重量级的开源项目。 在 Go 语言发布后,我就被其简洁、强大的特性所吸引,并于 2010 年开始在技术聚会上宣 传 Go 语言,当时所讲的题目是《Go 语言:互联网时代的 C》。现在看来,Go 语言确实很好地 解决了互联网时代开发的痛点,而且入门门槛不高,是一种上手容易、威力强大的工具。试想一 下,不需要学习复杂的异步逻辑,使用习惯的顺序方法,就能实现高性能的网络服务,并充分利 用系统的多个核心,这是多么美好的一件事情。 本书是国外 Go 社区多年经验积累的成果。本书默认读者已经具有一定的编程基础,希望更 好地使用 Go 语言。全书以示例为基础,详细介绍了 Go 语言中的一些比较深入的话题。对于有经 验的程序员来说,很容易通过学习书中的例子来解决自己实际工作中遇到的问题。辅以文字介绍, 读者会对相关问题有更系统的了解和认识。翻译过程中我尽量保持了原书的叙述方法,并加强了 叙述逻辑,希望读者会觉得清晰易读。 在翻译本书的过程中,感谢人民邮电出版社编辑杨海玲老师的指导和进度安排,让本书能 按时与读者见面。感谢谢孟军对译稿的审校,你的润色使译文读起来流畅了很多。尤其要感谢 我老婆对我的支持,感谢你能理解我出于热爱才会“匍匐”在计算机前码字。 最后,感谢读者购买此书。希望读者在探索 Go 语言的道路上,能够享受到和我一样的乐趣。
序 在计算机科学领域,提到不同寻常的人,总会有一些名字会闪现在你的脑海中。Rob Pike、 Robert Griesmier 和 Ken Thompson 就是其中几个。他们 3 个人负责构建过 UNIX、Plan 9、B、Java 的 JVM HotSpot、V8、Strongtalk ①、Sawzall、Ed、Acme 和 UTF8,此外还有很多其他的创造。 在 2007 年,这 3 个人凑在一起,尝试一个伟大的想法:综合他们多年的经验,借鉴已有的语言, 来创建一门与众不同的、全新的系统语言。他们随后以开源的形式发布了自己的实验成果,并将 这种语言命名为“Go”。如果按照现在的路线发展下去,这门语言将是这 3 个人最有影响的一项 创造。 当人们聚在一起,纯粹是为了让世界变得更好的时候,往往也是他们处于最佳状态的时候。 在 2013 年,为了围绕 Go 语言构建一个更好的社区,Brian 和 Erik 联合成立了 Gopher Academy, 没过多久,Bill 和其他一些有类似想法的人也加入迚来。他们首先注意到,社区需要有一个地方 可以在线聚集和分享素材,所以他们在 slack 创立了 Go 讨论版和 Gopher Academy 博客。随着时 间的推移,社区越来越大,他们创建了世界上第一个全球 Go 语言大会—GopherCon。随着与 社区更深入地交流,他们意识到还需要为广大想学习这门新语言的人提供一些资源,所以他们开 始着手写一本书,就是现在你手里拿的这本书。 为 Go 社区贡献了大量的时间和精力的 3 位作者,出于对 Go 语言社区的热爱写就了这本书。 我曾在 Bill、Brian 和 Erik 身边,见证了他们在不同的环境和角色(作为 Gopher Academy 博客的 编辑,作为大会组织者,甚至是在他们的日常工作中,作为父亲和丈夫)下,都会认真负责地撰 写和修订本书。对他们来说,这不仅仅是一本书,也是对他们心爱的语言的献礼。他们并不满足 于写就一本“好”书。他们编写、审校,再写、再修改,再三推敲每页文字、每个例子、每一章, 直到认为本书的内容配得上他们珍视的这门语言。 离开一门使用舒服、掌握熟练的语言,去学习一门不仅对自己来说,对整个世界来说都是全 新的语言,是需要勇气的。这是一条人迹罕至,沿途充满 bug,只有少数先行者熟悉的路。这里 ① 一个高性能强类型的 Smalltalk 实现。——译者注
ii 序 充满了意外的错误,文档不明确或者缺失,而且缺少可以拿来即用的代码库。这是拓荒者、先锋 才会选择的道路。如果你正在读这本书,那么你可能正在踏上这段旅途。 本书自始至终是为你—本书的读者精心制作的一本探索、学习和使用 Go 语言的简洁而全 面的指导手册。在全世界,你也不会找到比 Bill、Brian 和 Erik 更好的导师了。我非常高兴你能 开始探索 Go 语言的优点,期望能在线上和线下大会上遇到你。 Steve Francia Go 语言开发者,Hugo、Cobra、Viper 和 SPF13-VIM 的创建人
前言 那是 2013 年 10 月,我刚刚花几个月的时间写完 GoingGo.net 博客,就接到了 Brian Ketelsen 和 Erik St. Martin 的电话。他们正在写这本书,问我是否有兴趣参与迚来。我立刻抓住机会,参 与到写作中。当时,作为一个 Go 语言的新手,这是我迚一步了解这门语言的好机会。毕竟,与 Brian 和 Erik 一起工作、一起分享获得的知识,比我从构建博客中学到的要多得多。 完成前 4 章后,我们在 Manning 早期访问项目(MEAP)中发布了这本书。很快,我们收到 了来自语言团队成员的邮件。这位成员对很多细节提供了评审意见,还附加了大量有用的知识、 意见、鼓励和支持。根据这些评审意见,我们决定从头开始重写第 2 章,并对第 4 章迚行了全面 修订。据我们所知,对整章迚行重写的情况并不少见。通过这段重写的经历,我们学会要依靠社 区的帮助来完成写作,因为我们希望能立刻得到社区的支持。 自那以后,这本书就成了社区努力的成果。我们投入了大量的时间研究每一章,开发样例代 码,并和社区一起评审、讨论并编辑书中的材料和代码。我们尽了最大的努力来保证本书在技术 上没有错误,让代码符合通用习惯,并且使用社区认为应该有的方式来教 Go 语言。同时,我们 也融入了自己的思考、自己的实践和自己的指导方式。 我们希望本书能帮你学习 Go 语言,不仅是当下,就是多年以后,你也能从本书中找到有用 的东西。Brian、Erik 和我总会在线上帮助那些希望得到我们帮助的人。如果你购买了本书,谢 谢你,来和我们打个招呼吧。 William Kennedy
致谢 我们花了 18 个月的时间来写本书。但是,离开下面这些人的支持,我们不可能完成这本书: 我们的家人、朋友、同学、同事以及导师,整个 Go 社区,还有我们的出版商 Manning。 当你开始撰写类似的书时,你需要一位编辑。编辑不仅要分享喜悦与成就,而且要不惜一切 代价,帮你渡过难关。Jennifer Stout,你才华横溢,善于指导,是很棒的朋友。感谢你这段时间 的付出,尤其是在我们最需要你的时候。感谢你让这本书变成现实。还要感谢为本书的开发和出 版作出贡献的 Manning 的其他人。 每个人都不可能知晓一切,所以需要社区里的人付出时间和学识。感谢 Go 社区以及所有参 与本书不同阶段书稿评审并提供反馈的人。特别感谢 Adam McKay、Alex Basile、Alex Jacinto、 Alex Vidal、Anjan Bacchu、Benoît Benedetti、Bill Katz、Brian Hetro、Colin Kennedy、Doug Sparling,、 Jeffrey Lim、Jesse Evans、Kevin Jackson、Mark Fisher、Matt Zulak、Paulo Pires、Peter Krey、Philipp K. Janert、Sam Zaydel 以及 Thomas O’Rourke。还要感谢 Jimmy Frasché,他在出版前对本书书稿 做了快速、准确的技术审校。 这里还需要特别感谢一些人。 Kim Shrier,从最开始就在提供评审意见,并花时间来指导我们。我们从你那里学到了很多, 非常感谢。因为你,本书在技术上达到了更好的境界。 Bill Hathaway 在写书的最后一年,深入参与,并矫正了每一章。你的想法和意见非常宝贵。 我们必须给予 Bill“第 9 章合著者”的头衔。没有 Bill 的参与、天赋以及努力,就没有这一章的 存在。 我们还要特别感谢 Cory Jacobson、Jeffery Lim、Chetan Conikee 和 Nan Xiao 为本书持续提供 了评审意见和指导,感谢 Gabriel Aszalos、Fatih Arslan、Kevin Gillette 和 Jason Waldrip 帮助评审 样例代码,还要特别感谢 Steve Francia 帮我们作序,认可我们的工作。 最后,我们真诚地感谢我们的家人和朋友。为本书付出的时间和代价,总会影响到你所 爱的人。
ii 致谢 William Kennedy 我首先要感谢 Lisa,我美丽的妻子,以及我的 5 个孩子:Brianna、Melissa、Amanda、Jarrod 和 Thomas。Lisa,我知道你和孩子们有太多的日夜和周末,缺少丈夫和父亲的陪伴。感谢你让 我这段时间全力投入本书的工作:我爱你们,爱你们每一个人。 我也要感谢我生意上的伙伴 Ed Gonzalez、创意经理 Erick Zelaya,以及整个 Ardan 工作室的 团队。Ed,感谢你从一开始就支持我。没有你,我就无法完成本书。你不仅是生意伙伴,还是朋 友和兄长:谢谢你。Erick,感谢你为我、为公司做的一切。我不确定没有你,我们还能不能做到 这一切。 Brian Ketelsen 首先要感谢我的家人在我写书的这 4 年间付出的耐心。Christine、Nathan、Lauren 和 Evelyn, 感谢你们在游泳时放过在旁边椅子上写作的我,感谢你们相信这本书一定会出版。 Erik St. Martin 我要感谢我的未婚妻 Abby 以及我的 3 个孩子 Halie、Wyatt 和 Allie。感谢你们对我花大量时 间写书和组织会议如此耐心和理解。我非常爱你们,有你们我非常幸运。 还要感谢 Bill Kennedy 为本书付出的巨大努力,以及当我们需要他的帮助的时候,他总是立 刻想办法组织 GopherCon 来满足我们的要求。还要感谢整个社区出力评审并给出一些鼓励的话。
关于本书 Go 是一门开源的编程语言,目的在于降低构建简单、可靠、高效软件的门槛。尽管这门语 言借鉴了很多其他语言的思想,但是凭借自身统一和自然的表达,Go 程序在本质上完全不同于 用其他语言编写的程序。Go 平衡了底层系统语言的能力,以及在现代语言中所见到的高级特性。 你可以依靠 Go 语言来构建一个非常快捷、高性能且有足够控制力的编程环境。使用 Go 语言, 可以写得更少,做得更多。 谁应该读这本书 本书是写给已经有一定其他语言编程经验,并且想学习 Go 语言的中级开发者的。我们写这 本书的目的是,为读者提供一个专注、全面且符合语言习惯的视角。我们同时关注语言的规范和 实现,涉及的内容包括语法、类型系统,并发、通道、测试以及其他一些主题。我们相信,对于 刚开始学 Go 语言的人,以及想要深入了解这门语言内部实现的人来说,本书都是极佳的选择。 章节速览 本书由 9 章组成,每章内容简要描述如下。  第 1 章快速介绍这门语言是什么,为什么要创造这门语言,以及这门语言要解决什么问 题。这一章还会简要介绍一些 Go 语言的核心概念,如并发。  第 2 章引导你完成一个完整的 Go 程序,并教你 Go 作为一门编程语言必须提供的特性。  第 3 章介绍打包的概念,以及搭建 Go 工作空间和开发环境的最佳实践。这一章还会展 示如何使用 Go 语言的工具链,包括获取和构建代码。  第 4 章展示 Go 语言内置的类型,即数组、切片和映射。还会解释这些数据结构背后的 实现和机制。  第 5 章详细介绍 Go 语言的类型系统,从结构体类型到具名类型,再到接口和类型嵌套。这
ii 关于本书 一章还会展示如何综合利用这些数据结构,用简单的方法来设计结构并编写复杂的软件。 第 6 章深入展示 Go 调度器、并发和通道是如何工作的。这一章还将介绍这个方面背后 的机制。 第 7章基于第 6章的内容,展示一些实际开发中用到的并发模式。你会学到为了控制任 务如何实现一个 goroutine池,以及如何利用池来复用资源。 第 8章对标准库进行探索,深入介绍 3个包,即 log、json和 io。这一章专门介绍这 3个包之间的某些复杂关系。 第 9 章以如何利用测试和基准测试框架来结束全书。读者会学到如何写单元测试、表组 测试以及基准测试,如何在文档中增加示例,以及如何把这些示例当作测试使用。 关于代码 本书中的所有代码都使用等宽字体表示,以便和周围的文字区分开。在很多代码清单中,代 码被注释是为了说明关键概念,并且有时在正文中会用数字编号来给出对应代码的其他信息。 本书的源代码既可以在 Manning 网站(www.manning.com/books/go-in-action)上下载①,也 可以在 GitHub(https://github.com/goinaction/code)上找到这些源代码。 读者在线 购买本书后,可以在线访问由Manning出版社提供的私有论坛。在这个论坛上可以对本书做评论, 咨询技术问题,并得到作者或其他读者的帮助。通过浏览器访问 www.manning.com/books/go-in-action 可以访问并订阅这个论坛。这个网页还提供了注册后如何访问论坛,论坛提供什么样的帮助,以 及论坛的行为准则等信息。 Manning向读者承诺提供一个读者之间以及读者和作者之间交流的场所。Manning并不承诺 作者一定会参与,作者参与论坛的行为完全出于作者自愿(没有报酬)。我们建议你向作者提一 些有挑战性的问题,否则可能提不起作者的兴趣。 只要本书未绝版,作者在线论坛以及早期讨论的存档就可以在出版商的网站上获取到。 关于作者 William Kennedy(@goinggodotnet)是 Ardan工作室的管理合伙人。这家工作室位于佛罗里 达州迈阿密,是一家专注移动、Web和系统开发的公司。他也是博客 GoingGo.net的作者,迈阿 密 Go聚会的组织者。从在培训公司 Ardan Labs开始,他就专注于 Go语言教学。无论是在当地, ① 本书源代码也可以从 www.epubit.com.cn本书网页免费下载。
还是在线上,经常可以在大会或者工作坊中看到他的身影。他总是找时间来帮助那些想获取 Go 语言知识、撰写博客和编码技能提升到更高水平的公司或个人。 Brian Ketelsen(@bketelsen)是 XOR Data Exchange 的 CIO 和联合创始人。Brian 也是每年 Go 语言大会(GohperCon)的合办者,同时也是 Gopher Academy 的创立者。作为专注于社区的 组织,Gopher Academy 一直在促进 Go 语言的发展和对 Go 语言开发者的培训。Brian 从 2010 年 就开始使用 Go 语言。 Erik St. Martin(@erikstmartin)是 XOR Data Exchange 的软件开发总监。他所在的公司专注 于大数据分析,最早在得克萨斯州奥斯汀,后来搬到了佛罗里达州坦帕湾。Erik 长时间为开源软 件及其社区做贡献。他是每年 GopherCon 的组织者,也是坦帕湾 Go 聚会的组织者。他非常热爱 Go 语言及 Go 语言社区,积极寻求促进社区成长的新方法。
关于封面插图 本书封面插图的标题为“来自东印度的人”。这幅图选自伦敦的 Thomas Jefferys 的《A Collection of the Dresses of Different Nations, Ancient and Modern》(4 卷),出版于 1757 年到 1772 年之间。书籍首页说明了这幅画的制作工艺是铜版雕刻,手工上色,外层用阿拉伯胶做保护。 Thomas Jefferys(1719—1771)被称作“地理界的乔治三世国王”。作为制图者,他在当时英国地 图商中处于领先地位。他为政府和其他官员雕刻和印刷地图,同时也制作大量的商业地图和地图 册,尤其是北美地图。他作为地图制作者的经历,点燃了他收集各地风俗服饰的兴趣,最终成就 了这部衣着集。 对遥远大陆的着迷以及对旅行的乐趣,是 18 世纪晚期才兴起的现象。这类收集品也风行一 时,向实地旅行家和空想旅行家们介绍各地的风俗。Jefferys 的画集如此多样,生动地向我们描 述了 200 年前世界上不同民族的独立特征。从那之后,衣着的特征发生了改变,那个时代不同地 区和国家的多样性,也逐渐消失。现在,很难再通过本地居民的服饰来区分他们所在的大陆。也 许,从乐观的方面看,也许,从乐观的角度来看,我们用文化的多样性换取了更加多样化的个人 生活——当然也是更加多样化和快节奏的科技生活。 在很难将一本计算机书与另一本区分开的时代,Manning 创造性地将两个世纪以前不同地区 的多样性,附着在计算机行业的图书封面上,借以来赞美计算机行业的创造力和进取精神也为 Jeffreys 的画带来了新的生命。
目录 1 1 2 3 4 目录 第 1 章 关于 Go 语言的介绍 1 1.1 用Go解决现代编程难题 2 1.1.1 开发速度 2 1.1.2 并发 3 1.1.3 Go 语言的类型系统 5 1.1.4 内存管理 7 1.2 你好,Go 7 1.3 小结 8 第2章 快速开始一个Go程序 9 2.1 程序架构 9 2.2 main包 11 2.3 search包 13 2.3.1 search.go 13 2.3.2 feed.go 21 2.3.3 match.go/default.go 24 2.4 RSS 匹配器 30 2.5 小结 36 第 3 章 打包和工具链 37 3.1 包 37 3.1.1 包名惯例 38 3.1.2 main包 38 3.2 导入 39 3.2.1 远程导入 40 3.2.2 命名导入 40 3.3 函数 init 41 3.4 使用 Go 的工具 42 3.5 进一步介绍 Go 开发 工具 44 3.5.1 go vet 44 3.5.2 Go 代码格式化 45 3.5.3 Go 语言的文档 45 3.6 与其他Go开发者合作 48 3.7 依赖管理 48 3.7.1 第三方依赖 49 3.7.2 对 gb 的介绍 50 3.8 小结 52 第 4 章 数组、切片和映射 53 4.1 数组的内部实现和基础 功能 53 4.1.1 内部实现 53 4.1.2 声明和初始化 54 4.1.3 使用数组 55 4.1.4 多维数组 58 4.1.5 在函数间传递数组 59 4.2 切片的内部实现和基础 功能 60 4.2.1 内部实现 60 4.2.2 创建和初始化 61 4.2.3 使用切片 63 4.2.4 多维切片 74 4.2.5 在函数间传递切片 75 4.3 映射的内部实现和基础 功能 76 4.3.1 内部实现 76 4.3.2 创建和初始化 78 4.3.3 使用映射 79 4.3.4 在函数间传递映射 81 4.4 小结 82
ii 目录 6 8 9 5 7 第 5章 Go语言的类型系统 83 5.1 用户定义的类型 83 5.2 方法 87 5.3 类型的本质 90 5.3.1 内置类型 91 5.3.2 引用类型 91 5.3.3 结构类型 93 5.4 接口 95 5.4.1 标准库 96 5.4.2 实现 98 5.4.3 方法集 99 5.4.4 多态 103 5.5 嵌入类型 105 5.6 公开或未公开的 标识符 113 5.7 小结 121 第 6 章 并发 122 6.1 并发与并行 122 6.2 goroutine 125 6.3 竞争状态 132 6.4 锁住共享资源 135 6.4.1 原子函数 135 6.4.2 互斥锁 138 6.5 通道 140 6.5.1 无缓冲的通道 141 6.5.2 有缓冲的通道 146 6.6 小结 149 第 7 章 并发模式 150 7.1 runner 150 7.2 pool 158 7.3 work 168 7.4 小结 174 第 8 章 标准库 176 8.1 文档与源代码 177 8.2 记录日志 178 8.2.1 log 包 179 8.2.2 定制的日志记录器 182 8.2.3 结论 186 8.3 编码/解码 187 8.3.1 解码 JSON 187 8.3.2 编码 JSON 192 8.3.3 结论 193 8.4 输入和输出 193 8.4.1 Writer和 Reader接口 194 8.4.2 整合并完成工作 195 8.4.3 简单的 curl 199 8.4.4 结论 200 8.5 小结 200 第 9 章 测试和性能 201 9.1 单元测试 201 9.1.1 基础单元测试 202 9.1.2 表组测试 205 9.1.3 模仿调用 208 9.1.4 测试服务端点 212 9.2 示例 217 9.3 基准测试 220 9.4 小结 224
第 1 章 关于 Go 语言的介绍 本章主要内容  用 Go 语言解决现代计算难题  使用 Go 语言工具 计算机一直在演化,但是编程语言并没有以同样的速度演化。现在的手机,内置的 CPU 核 数可能都多于我们使用的第一台电脑。高性能服务器拥有 64 核、128 核,甚至更多核。但是我 们依旧在使用为单核设计的技术在编程。 编程的技术同样在演化。大部分程序不再由单个开发者来完成,而是由处于不同时区、不同 时间段工作的一组人来完成。大项目被分解为小项目,指派给不同的程序员,程序员开发完成后, 再以可以在各个应用程序中交叉使用的库或者包的形式,提交给整个团队。 如今的程序员和公司比以往更加信任开源软件的力量。Go 语言是一种让代码分享更容易的编 程语言。Go 语言自带一些工具,让使用别人写的包更容易,并且 Go 语言也让分享自己写的包 更容易。 在本章中读者会看到 Go 语言区别于其他编程语言的地方。Go 语言对传统的面向对象开发 进行了重新思考,并且提供了更高效的复用代码的手段。Go 语言还让用户能更高效地利用昂贵 服务器上的所有核心,而且它编译大型项目的速度也很快。 在阅读本章时,读者会对影响 Go 语言形态的很多决定有一些认识,从它的并发模型到快如 闪电的编译器。我们在前言中提到过,这里再强调一次:这本书是写给已经有一定其他编程语言 经验、想学习 Go 语言的中级开发者的。本书会提供一个专注、全面且符合习惯的视角。我们同 时专注语言的规范和实现,涉及的内容包括语法、Go 语言的类型系统、并发、通道、测试以及 其他一些非常广泛的主题。我们相信,对刚开始要学习 Go 语言和想要深入了解语言内部实现的 人来说,本书都是最佳选择。 本书示例中的源代码可以在 https://github.com/goinaction/code 下载。 我们希望读者能认识到,Go 语言附带的工具可以让开发人员的生活变得更简单。最后,读 者会意识到为什么那么多开发人员用 Go 语言来构建自己的新项目。 1第 1 章 关于 Go 语言的介绍
1.1 用 Go 解决现代编程难题 Go 语言开发团队花了很长时间来解决当今软件开发人员面对的问题。开发人员在为项目选 择语言时,不得不在快速开发和性能之间做出选择。C 和 C++这类语言提供了很快的执行速度, 而 Ruby 和 Python 这类语言则擅长快速开发。Go 语言在这两者间架起了桥梁,不仅提供了高性 能的语言,同时也让开发更快速。 在探索 Go 语言的过程中,读者会看到精心设计的特性以及简洁的语法。作为一门语言,Go 不仅定义了能做什么,还定义了不能做什么。Go 语言的语法简洁到只有几个关键字,便于记忆。 Go 语言的编译器速度非常快,有时甚至会让人感觉不到在编译。所以,Go 开发者能显著减少等 待项目构建的时间。因为 Go 语言内置并发机制,所以不用被迫使用特定的线程库,就能让软件 扩展,使用更多的资源。Go 语言的类型系统简单且高效,不需要为面向对象开发付出额外的心 智,让开发者能专注于代码复用。Go 语言还自带垃圾回收器,不需要用户自己管理内存。让我 们快速浏览一下这些关键特性。 1.1.1 开发速度 编译一个大型的 C 或者 C++项目所花费的时间甚至比去喝杯咖啡的时间还长。图 1-1 是 XKCD 中的一幅漫画,描述了在办公室里开小差的经典借口。 图 1-1 努力工作?(来自 XKCD) Go 语言使用了更加智能的编译器,并简化了解决依赖的算法,最终提供了更快的编译速度。 编译 Go 程序时,编译器只会关注那些直接被引用的库,而不是像 Java、C 和 C++那样,要遍历 依赖链中所有依赖的库。因此,很多 Go 程序可以在 1 秒内编译完。在现代硬件上,编译整个 Go
语言的源码树只需要 20 秒。 因为没有从编译代码到执行代码的中间过程,用动态语言编写应用程序可以快速看到输出。 代价是,动态语言不提供静态语言提供的类型安全特性,不得不经常用大量的测试套件来避免在 运行的时候出现类型错误这类 bug。 想象一下,使用类似 JavaScript 这种动态语言开发一个大型应用程序,有一个函数期望接收 一个叫作 ID 的字段。这个参数应该是整数,是字符串,还是一个 UUID?要想知道答案,只能 去看源代码。可以尝试使用一个数字或者字符串来执行这个函数,看看会发生什么。在 Go 语言 里,完全不用为这件事情操心,因为编译器就能帮用户捕获这种类型错误。 1.1.2 并发 作为程序员,要开发出能充分利用硬件资源的应用程序是一件很难的事情。现代计算机都拥 有多个核,但是大部分编程语言都没有有效的工具让程序可以轻易利用这些资源。这些语言需要 写大量的线程同步代码来利用多个核,很容易导致错误。 Go 语言对并发的支持是这门语言最重要的特性之一。goroutine 很像线程,但是它占用的 内存远少于线程,使用它需要的代码更少。通道(channel)是一种内置的数据结构,可以让 用户在不同的 goroutine 之间同步发送具有类型的消息。这让编程模型更倾向于在 goroutine 之间发送消息,而不是让多个 goroutine 争夺同一个数据的使用权。让我们看看这些特性的 细节。 1.goroutine goroutine 是可以与其他 goroutine 并行执行的函数,同时也会与主程序(程序的入口)并行 执行。在其他编程语言中,你需要用线程来完成同样的事情,而在 Go 语言中会使用同一个线程 来执行多个 goroutine。例如,用户在写一个 Web 服务器,希望同时处理不同的 Web 请求,如果 使用 C 或者 Java,不得不写大量的额外代码来使用线程。在 Go 语言中,net/http 库直接使用了 内置的 goroutine。每个接收到的请求都自动在其自己的 goroutine 里处理。goroutine 使用的内存 比线程更少,Go 语言运行时会自动在配置的一组逻辑处理器上调度执行 goroutine。每个逻辑处 理器绑定到一个操作系统线程上(见图 1-2)。这让用户的应用程序执行效率更高,而开发工作量 显著减少。 如果想在执行一段代码的同时,并行去做另外一些事情,goroutine 是很好的选择。下面是一 个简单的例子: func log(msg string) { ...这里是一些记录日志的代码 } // 代码里有些地方检测到了错误 go log("发生了可怕的事情")
图 1-2 在单一系统线程上执行多个 goroutine 关键字 go 是唯一需要去编写的代码,调度 log 函数作为独立的 goroutine 去运行,以便与 其他 goroutine 并行执行。这意味着应用程序的其余部分会与记录日志并行执行,通常这种并行 能让最终用户觉得性能更好。就像之前说的,goroutine 占用的资源更少,所以常常能启动成千上 万个 goroutine。我们会在第 6 章更加深入地探讨 goroutine 和并发。 2.通道 通道是一种数据结构,可以让 goroutine 之间进行安全的数据通信。通道可以帮用户避免其 他语言里常见的共享内存访问的问题。 并发的最难的部分就是要确保其他并发运行的进程、线程或 goroutine 不会意外修改用户的 数据。当不同的线程在没有同步保护的情况下修改同一个数据时,总会发生灾难。在其他语言中, 如果使用全局变量或者共享内存,必须使用复杂的锁规则来防止对同一个变量的不同步修改。 为了解决这个问题,通道提供了一种新模式,从而保证并发修改时的数据安全。通道这一模 式保证同一时刻只会有一个 goroutine 修改数据。通道用于在几个运行的 goroutine 之间发送数据。 在图 1-3 中可以看到数据是如何流动的示例。想象一个应用程序,有多个进程需要顺序读取或者 修改某个数据,使用 goroutine 和通道,可以为这个过程建立安全的模型。 图 1-3 使用通道在 goroutine 之间安全地发送数据
图 1-3 中有 3 个 goroutine,还有 2 个不带缓存的通道。第一个 goroutine 通过通道把数 据传给已经在等待的第二个 goroutine。在两个 goroutine 间传输数据是同步的,一旦传输完 成,两个 goroutine 都会知道数据已经完成传输。当第二个 goroutine 利用这个数据完成其任 务后,将这个数据传给第三个正在等待的 goroutine。这次传输依旧是同步的,两个 goroutine 都会确认数据传输完成。这种在 goroutine 之间安全传输数据的方法不需要任何锁或者同步 机制。 需要强调的是,通道并不提供跨 goroutine 的数据访问保护机制。如果通过通道传输数据的 一份副本,那么每个 goroutine 都持有一份副本,各自对自己的副本做修改是安全的。当传输的 是指向数据的指针时,如果读和写是由不同的 goroutine 完成的,每个 goroutine 依旧需要额外的 同步动作。 1.1.3 Go 语言的类型系统 Go 语言提供了灵活的、无继承的类型系统,无需降低运行性能就能最大程度上复用代码。 这个类型系统依然支持面向对象开发,但避免了传统面向对象的问题。如果你曾经在复杂的 Java 和 C++程序上花数周时间考虑如何抽象类和接口,你就能意识到 Go 语言的类型系统有多么简单。 Go 开发者使用组合(composition)设计模式,只需简单地将一个类型嵌入到另一个类型,就能 复用所有的功能。其他语言也能使用组合,但是不得不和继承绑在一起使用,结果使整个用法非 常复杂,很难使用。在 Go 语言中,一个类型由其他更微小的类型组合而成,避免了传统的基于 继承的模型。 另外,Go 语言还具有独特的接口实现机制,允许用户对行为进行建模,而不是对类型进行 建模。在 Go 语言中,不需要声明某个类型实现了某个接口,编译器会判断一个类型的实例是否 符合正在使用的接口。Go 标准库里的很多接口都非常简单,只开放几个函数。从实践上讲,尤 其对那些使用类似 Java 的面向对象语言的人来说,需要一些时间才能习惯这个特性。 1.类型简单 Go 语言不仅有类似 int 和 string 这样的内置类型,还支持用户定义的类型。在 Go 语言 中,用户定义的类型通常包含一组带类型的字段,用于存储数据。Go 语言的用户定义的类型看 起来和 C 语言的结构很像,用起来也很相似。不过 Go 语言的类型可以声明操作该类型数据的方 法。传统语言使用继承来扩展结构——Client 继承自 User,User 继承自 Entity,Go 语言与此不同, Go 开发者构建更小的类型——Customer 和 Admin,然后把这些小类型组合成更大的类型。图 1-4 展示了继承和组合之间的不同。 2.Go 接口对一组行为建模 接口用于描述类型的行为。如果一个类型的实例实现了一个接口,意味着这个实例可以执行
The above is a preview of the first 20 pages. Register to read the complete e-book.