1、CMYCMMYCYCMYKGo语言学习笔记fy.pdf 1 2016/6/3 15:19:11 内 容 简 介 作为时下流行的一种系统编程语言,Go 简单易学,性能很好,且支持各类主流平台。已有大量项目采用 Go 编写,这其中就包括 Docker 等明星作品,其开发和执行效率早已被证明。本书经四年多逐步完善,内容覆盖了语言、运行时、性能优化、工具链等各层面知识。且内容经大量读者反馈和校对,没有明显的缺陷和错误。上卷细致解析了语言规范相关细节,便于读者深入理解语言相关功能的使用方法和注意事项。下卷则对运行时源码做出深度剖析,引导读者透彻了解语言功能背后的支持环境和运行体系,诸如内存分配、垃圾回收
2、和并发调度等。本书不适合编程初学者入门,可供有实际编程经验或正在使用 Go 工作的人群参考。未经许可,不得以任何方式复制或抄袭本书之部分或全部内容。版权所有,侵权必究。图书在版编目(CIP)数据 Go 语言学习笔记/雨痕著.北京:电子工业出版社,2016.7 ISBN 978-7-121-29160-9 .G.雨.程序语言程序设计.TP312 中国版本图书馆 CIP 数据核字(2016)第 141787 号 策划编辑:许 艳 责任编辑:许 艳 印 刷:装 订:出版发行:电子工业出版社 北京市海淀区万寿路 173 信箱 邮编:100036 开 本:787980 1/16 印张:29.25 字数:
3、552 千字 版 次:2016 年 7 月第 1 版 印 次:2016 年 7 月第 1 次印刷 定 价:89.00 元 凡所购买电子工业出版社图书有缺损问题,请向购买书店调换。若书店售缺,请与本社发行部联系,联系及邮购电话:(010)88254888,88258888。质量投诉请发邮件至 ,盗版侵权举报请发邮件至 。本书咨询联系方式:010-51260888-819 。前言 III 前言 前两天忙里偷闲将第五版Go 学习笔记上下册合并,预备交给出版社编辑。不经意扫了一眼更新记录,才发觉四年光阴恍然而过。不知从何时起,岁月流逝的速度越来越快,抓不得,留不住。我很擅长坚持,不知是因为笨,还是性情
4、迟钝的缘故。在给编辑写作者简介时,我努力回忆自己最近二十年的经历,好像除了些纷扰的人和事外,就是一段段在不同技术圈子里日夜探索的记忆,历久弥新。现在带了些学生,每每交流时,总偷偷庆幸自己是个先行者,没有互联网的“黑暗时代”反而造就了踏实的基础,远不是现今乱花迷眼的境况。看着他们对于具体实现“懵懂无知”的表现,我对于写书这事就愈发虔诚,生怕误了别人的光阴和热情。似乎学习笔记这个名字才是最好的诠释,立不得案头,权作闲书,稍能观感一二即可。因喜爱 C,故对 Go 关注得很早。观望良久,终究受不住诱惑,一头栽了进去。边学边记,于是有了最早的学习笔记。只因错漏过多,发到某论坛着实没砸出什么水花来。此后,
5、对于宣传也淡了心思,再不愿出去,只自己默默更新,或发到微博,给一些熟识尚惦记这事的人打个招呼。某日,一编辑发来消息,询问我是否出版,才恍然知道这书原也是可印的,好像自己从没想过。犹豫再三,且将几本笔记从 GitHub 下架。只可惜,因某些理念不同,最终未能如愿,这一拖就是许多时日。去年受老谢的邀请,前往上海参加 Gopher China 大会。期间多次被问及何时能有实体书出版,熄了许久的心思方又活过来。年中,重新写了书稿,年底几乎又重来一遍,心底对于出书总有些忐忑。直到圣诞节,才放了下册出来。幸好,并没有人出来指责我粗制滥造,方得心安。Go 语言学习笔记 IV 我儿小乖还太小,于是猴年我一人回
6、老家过年。也许是在外面太久,对搬进城里的老家全然陌生,每日里除了陪父母吃饭外,其他时间都用来写上册书稿。偶尔透过窗看见远处的山影,才找回些幼时记忆。书写得意外顺利,即便网络不算通畅也未能影响到我。回京路上,我彻底定了主意,准备交付出版。节后忙于培训一事,书稿校对稍稍拖后了些。边按章节调整,边请群里的伙伴们帮忙审校,所幸赶在截止日期前完成。样稿交到编辑手里,虽尚有些收尾工作,但总算能放轻松些。这于我是个解脱,困于此的心思总算少了一大半。依惯例,需在此感谢很多人。其中自然少不了对我多加鼓励的家中太上领导和惦记良久的网络众位大仙们。当然,最需感谢的是群里帮忙校对的小伙伴们,有溺水的鱼、大内总管、st
7、archou、老虎、日下、小 E、春婶、奋斗娃等等。读者定位 本书并不适合用作编程初学者入门,因内容和文体都太过简练了些。我厚脸推荐给有实际经验或正用 Go 工作的人群,可于路途中当闲书翻看几页。联系方式 鉴于能力有限,书中难免错漏。如您看到任何问题,请与我联系,以便更正。谢谢!微博: 邮件: 社区: 雨 痕 二一六年春 本书的版本历程 V 本书的版本历程 2012-01-11 开始学习 Go。2012-01-15 第一版,基于 R60。2012-03-29 升级到 1.0。2012-06-15 升级到 1.0.2。2013-03-26 升级到 1.1。2013-12-12 第二版,基于 1.
8、2。2014-05-22 第三版,基于 1.3。2014-12-20 第四版,基于 1.4。2015-06-15 第五版,基于 1.5。2015-11-01 全新学习笔记.第五版。2015-12-09 下卷源码剖析截稿,基于 1.5.1。2016-04-01 上卷语言详解截稿,基于 1.6。Go 语言学习笔记 VI 目录 上卷 语言详解 第 1 章 概述.3 1.1 特征.3 1.2 简介.6 第 2 章 类型.18 2.1 变量.18 2.2 命名.22 2.3 常量.24 2.4 基本类型.28 2.5 引用类型.31 2.6 类型转换.33 2.7 自定义类型.34 第 3 章 表达式.
9、38 3.1 保留字.38 3.2 运算符.38 3.3 初始化.44 3.4 流控制.45 目录 VII 第 4 章 函数.59 4.1 定义.59 4.2 参数.63 4.3 返回值.67 4.4 匿名函数.69 4.5 延迟调用.76 4.6 错误处理.80 第 5 章 数据.86 5.1 字符串.86 5.2 数组.95 5.3 切片.100 5.4 字典.110 5.5 结构.118 第 6 章 方法.130 6.1 定义.130 6.2 匿名字段.133 6.3 方法集.134 6.4 表达式.136 第 7 章 接口.141 7.1 定义.141 7.2 执行机制.145 7.3
10、 类型转换.150 7.4 技巧.151 第 8 章 并发.153 8.1 并发的含义.153 8.2 通道.163 Go 语言学习笔记 VIII 8.3 同步.183 第 9 章 包结构.187 9.1 工作空间.187 9.2 导入包.188 9.3 组织结构.192 9.4 依赖管理.197 第 10 章 反射.200 10.1 类型.200 10.2 值.207 10.3 方法.210 10.4 构建.212 10.5 性能.213 第 11 章 测试.216 11.1 单元测试.216 11.2 性能测试.221 11.3 代码覆盖率.224 11.4 性能监控.226 第 12 章
11、 工具链.229 12.1 安装.229 12.2 工具.231 12.3 编译.234 下卷 源码剖析 第 13 章 准备.243 第 14 章 引导.244 目录 IX 第 15 章 初始化.247 第 16 章 内存分配.255 16.1 概述.255 16.2 初始化.259 16.3 分配.265 16.4 回收.279 16.5 释放.283 16.6 其他.285 第 17 章 垃圾回收.291 17.1 概述.291 17.2 初始化.293 17.3 启动.294 17.4 标记.300 17.5 清理.311 17.6 监控.314 17.7 其他.317 第 18 章 并
12、发调度.326 18.1 概述.326 18.2 初始化.327 18.3 任务.332 18.4 线程.344 18.5 执行.353 18.6 连续栈.370 18.7 系统调用.385 18.8 监控.390 18.9 其他.396 Go 语言学习笔记 X 第 19 章 通道.407 19.1 创建.407 19.2 收发.408 19.3 选择.418 第 20 章 延迟.427 20.1 定义.427 20.2 性能.433 20.3 错误.434 第 21 章 析构.438 21.1 设置.438 21.2 清理.443 21.3 执行.445 第 22 章 缓存池.450 22.
13、1 初始化.450 22.2 操作.453 22.3 清理.455 上卷 语言详解 1 上卷 语言详解 基于 Go 1.6 Go 语言学习笔记 2 第 1 章 概述 3 第 1 章 概述 对我而言,Go 是一门很有意思的编程语言。虽算不得优雅,但也不浅薄。自 C 一脉相承,又吸收了些时髦的东西。最重要的是,它依旧简单。我喜欢简单,平日里也是竭尽所能将复杂的东西简单化。有关 Go 的宣传语已经太多,优点或缺点都能罗列出长长的清单。我甚至不知道该如何做才能堆砌出本章内容,所以一直拖到全书的最后才去完成。1.1 特征 我并不想,似乎也没资格为 Go 增添什么新的荣誉。在此仅从这几年的使用经验说说个人
14、看法,一如书名学习笔记那样。语法简单 抛开语法样式不谈,单就类型和规则而言,Go 与 C99、C11 相似之处颇多,这也是我能接受它被冠以“NextC”名号的重要原因。即便我是个坚定的 C 拥趸,也不得不承认,它处于简单和复杂的两极。C 简单到你每写下一行代码,都能在脑中想象出编译后的模样,指令如何执行,内存如何分配,等等。而 C 的复杂在于,它有太多隐晦而不着边际的规则,着实让人头疼。相比较而言,Go从零开始,没有历史包袱,在汲取众多经验教训后,可从头规划一个规则严谨、条理简单的世界。人们习惯拿关键字和控制语句的数量来作为 Go 简单的例证,我倒觉着这并不合适。诚Go 语言学习笔记 4 然,
15、更少的语言规则有助于入门学习,这无可厚非。但更重要的在于,语言规则严谨,没有歧义,更没什么黑魔法变异用法。任何人写出的代码都基本一致,这才是简单的本质。放弃部分“灵活”和“自由”,换来更好的维护性,我觉得是值得的。将“+”、“-”从运算符降级为语句,保留指针,但默认阻止指针运算。初时的不习惯,并不能掩盖它们带来的长期的好处。还有,将切片和字典作为内置类型,从运行时的层面进行优化,这也算是一种“简单”。并发模型 时至今日,并发编程已成为程序员的基本技能,在各个技术社区都能看到诸多与之相关的讨论主题。究竟哪种方式是最佳并发编程体验,或许会一直争论下去。但 Go 却一反常态做了件极大胆的事,从根子上
16、将一切都并发化,运行时用 Goroutine 运行所有的一切,包括 main.main 入口函数。可以说,Goroutine 是 Go 最显著的特征。它用类协程的方式来处理并发单元,却又在运行时层面做了更深度的优化处理。这使得语法上的并发编程变得极为容易,无须处理回调,无须关注执行绪切换,仅一个关键字,简单而自然。搭配 channel,实现 CSP 模型。将并发单元间的数据耦合拆解开来,各司其职,这对所有纠结于内存共享、锁粒度的开发人员都是一个可期盼的解脱。若说有所不足,那就是应该有个更大的计划,将通信从进程内拓展到进程外,实现真正意义上的分布式。内存分配 将一切并发化固然是好,但带来的问题同样很多。如何实现高并发下的内存分配和管理就是个难题。好在 Go 选择了 tcmalloc,它本就是为并发而设计的高性能内存分配组件。可以说,内存分配器是运行时三大组件里变化最少的部分。刨去因配合垃圾回收器而修改的内容,内存分配器完整保留了 tcmalloc 的原始架构。使用 cache 为当前执行线程提供无锁分配,多个 central 在不同线程间平衡内存单元复用。在更高层次里,heap 则管理着