转为 mdbook

This commit is contained in:
chai2010
2022-08-04 14:58:52 +08:00
parent 7fa86ea953
commit 06a1bdf735
49 changed files with 3695 additions and 236 deletions

View File

@@ -1,88 +1,109 @@
# Go语言圣经中文版
Go语言圣经 [《The Go Programming Language》](http://gopl.io) 中文版本仅供学习交流之用。对于希望学习CGO、Go汇编语言等高级用法的同学我们推荐[《Go语言高级编程》](https://github.com/chai2010/advanced-go-programming-book)开源图书。如果希望深入学习Go语言语法树结构可以参考[《Go语法树入门——开启自制编程语言和编译器之旅》](https://github.com/chai2010/go-ast-book)。如果想从头实现一个玩具Go语言可以参考[《从头实现µGo语言》](https://github.com/chai2010/ugo-compiler-book)。
[![](cover_middle.jpg)](https://github.com/golang-china/gopl-zh)
- 项目主页http://github.com/golang-china/gopl-zh
- 原版官网http://gopl.io
译者信息:
- 译者柴树杉Github [@chai2010](https://github.com/chai2010)Twitter [@chaishushan](https://twitter.com/chaishushan)
- 译者Xargin, https://github.com/cch123
- 译者CrazySssst
- 译者foreversmart <njutree@gmail.com>
## 关注微信公众号光谷码农和 TechPaper
<table>
<tr>
<td>
<img width="222px" src="https://github.com/chai2010/advanced-go-programming-book/raw/master/css.png">
</td>
<td>
<img width="222px" src="https://github.com/chai2010/advanced-go-programming-book/raw/master/cch.png">
</td>
</tr>
</table>
## 在线预览
- https://docs.hacknode.org/gopl-zh/
- https://books.studygolang.com/gopl-zh/
- https://wizardforcel.gitbooks.io/gopl-zh/
- https://book.itsfun.top/gopl-zh/ #每夜自动构建
{% include "./version.md" %}
-------
# 译者序
在上个世纪70年代贝尔实验室的[Ken Thompson][KenThompson]和[Dennis M. Ritchie][DennisRitchie]合作发明了[UNIX](http://doc.cat-v.org/unix/)操作系统,同时[Dennis M. Ritchie][DennisRitchie]为了解决[UNIX](http://doc.cat-v.org/unix/)系统的移植性问题而发明了C语言贝尔实验室的[UNIX](http://doc.cat-v.org/unix/)和C语言两大发明奠定了整个现代IT行业最重要的软件基础目前的三大桌面操作系统的中[Linux](http://www.linux.org/)和[Mac OS X](http://www.apple.com/cn/osx/)都是源于[UNIX]()系统两大移动平台的操作系统iOS和Android也都是源于[UNIX](http://doc.cat-v.org/unix/)系统。C系家族的编程语言占据统治地位达几十年之久。在[UNIX]()和C语言发明40年之后目前已经在Google工作的[Ken Thompson](http://genius.cat-v.org/ken-thompson/)和[Rob Pike](http://genius.cat-v.org/rob-pike/)(他们在贝尔实验室时就是同事)、还有[Robert Griesemer](http://research.google.com/pubs/author96.html)设计了V8引擎和HotSpot虚拟机一起合作为了解决在21世纪多核和网络化环境下越来越复杂的编程问题而发明了Go语言。从Go语言库早期代码库日志可以看出它的演化历程Git用`git log --before={2008-03-03} --reverse`命令查看):
![](./images/go-log04.png)
从早期提交日志中也可以看出Go语言是从[Ken Thompson](http://genius.cat-v.org/ken-thompson/)发明的B语言、[Dennis M. Ritchie](http://genius.cat-v.org/dennis-ritchie/)发明的C语言逐步演化过来的是C语言家族的成员因此很多人将Go语言称为21世纪的C语言。纵观这几年来的发展趋势Go语言已经成为云计算、云存储时代最重要的基础编程语言。
在C语言发明之后约5年的时间之后1978年[Brian W. Kernighan](http://www.cs.princeton.edu/~bwk/)和[Dennis M. Ritchie](http://genius.cat-v.org/dennis-ritchie/)合作编写出版了C语言方面的经典教材《[The C Programming Language](http://s3-us-west-2.amazonaws.com/belllabs-microsite-dritchie/cbook/index.html)》该书被誉为C语言程序员的圣经作者也被大家亲切地称为[K&R](https://en.wikipedia.org/wiki/K%26R)。同样在Go语言正式发布2009年约5年之后2014年开始写作2015年出版由Go语言核心团队成员[Alan A. A. Donovan](https://github.com/adonovan)和[K&R](https://en.wikipedia.org/wiki/K%26R)中的[Brian W. Kernighan](http://www.cs.princeton.edu/~bwk/)合作编写了Go语言方面的经典教材《[The Go Programming Language](http://gopl.io)》。Go语言被誉为21世纪的C语言如果说[K&R](https://en.wikipedia.org/wiki/K%26R)所著的是圣经的旧约那么D&K所著的必将成为圣经的新约。该书介绍了Go语言几乎全部特性并且随着语言的深入层层递进对每个细节都解读得非常细致每一节内容都精彩不容错过是广大Gopher的必读书目。大部分Go语言核心团队的成员都参与了该书校对工作因此该书的质量是可以完全放心的。
同时单凭阅读和学习其语法结构并不能真正地掌握一门编程语言必须进行足够多的编程实践——亲自编写一些程序并研究学习别人写的程序。要从利用Go语言良好的特性使得程序模块化充分利用Go的标准函数库以Go语言自己的风格来编写程序。书中包含了上百个精心挑选的习题希望大家能先用自己的方式尝试完成习题然后再参考官方给出的解决方案。
该书英文版约从2015年10月开始公开发售其中日文版本最早参与翻译和审校参考致谢部分。在2015年10月我们并不知道中文版是否会及时引进、将由哪家出版社引进、引进将由何人来翻译、何时能出版这些信息都成了一个秘密。中国的Go语言社区是全球最大的Go语言社区我们从一开始就始终紧跟着Go语言的发展脚步。我们应该也完全有能力以中国Go语言社区的力量同步完成Go语言圣经中文版的翻译工作。与此同时国内有很多Go语言爱好者也在积极关注该书本人也在第一时间购买了纸质版本[亚马逊价格314人民币](http://www.amazon.cn/The-Go-Programming-Language-Donovan-Alan-A-A/dp/0134190440/)。补充:国内也即将出版英文版,[价格79元](http://product.china-pub.com/4912464)。为了Go语言的学习和交流大家决定合作免费翻译该书。
翻译工作从2015年11月20日前后开始到2016年1月底初步完成前后历时约2个月时间在其它语言版本中全球第一个完成翻译的基本做到和原版同步。其中[chai2010](https://github.com/chai2010)翻译了前言、第2 ~ 4章、第10 ~ 13章[Xargin](https://github.com/cch123)翻译了第1章、第6章、第8 ~ 9章[CrazySssst](https://github.com/CrazySssst)翻译了第5章[foreversmart](https://github.com/foreversmart)翻译了第7章大家共同参与了基本的校验工作还有其他一些朋友提供了积极的反馈建议。如果大家还有任何问题或建议可以直接到中文版项目页面提交[Issue](https://github.com/golang-china/gopl-zh/issues),如果发现英文版原文在[勘误](http://www.gopl.io/errata.html)中未提到的任何错误,可以直接去[英文版项目](https://github.com/adonovan/gopl.io/)提交。
最后希望这本书能够帮助大家用Go语言快乐地编程。
2016年 1月 于 武汉
-------
# 前言
*“Go是一个开源的编程语言它很容易用于构建简单、可靠和高效的软件。”摘自Go语言官方网站http://golang.org *
## Go语言起源
Go语言由来自Google公司的[Robert Griesemer](http://research.google.com/pubs/author96.html)[Rob Pike](http://genius.cat-v.org/rob-pike/)和[Ken Thompson](http://genius.cat-v.org/ken-thompson/)三位大牛于2007年9月开始设计和实现然后于2009年的11月对外正式发布译注关于Go语言的创世纪过程请参考 http://talks.golang.org/2015/how-go-was-made.slide )。语言及其配套工具的设计目标是具有表达力,高效的编译和执行效率,有效地编写高效和健壮的程序
编程语言的演化跟生物物种的演化类似,一个成功的编程语言的后代一般都会继承它们祖先的优点;当然有时多种语言杂合也可能会产生令人惊讶的特性;还有一些激进的新特性可能并没有先例。通过观察这些影响,我们可以学到为什么一门语言是这样子的,它已经适应了怎样的环境
Go语言有着和C语言类似的语法外表和C语言一样是专业程序员的必备工具可以用最小的代价获得最大的战果
但是它不仅仅是一个更新的C语言。它还从其他语言借鉴了很多好的想法同时避免引入过度的复杂性。
Go语言中和并发编程相关的特性是全新的也是有效的同时对数据抽象和面向对象编程的支持也很灵活。
Go语言同时还集成了自动垃圾收集技术用于更好地管理内存。
下图展示了有哪些早期的编程语言对Go语言的设计产生了重要影响
Go语言尤其适合编写网络服务相关基础设施同时也适合开发一些工具软件和系统软件。
但是Go语言确实是一个通用的编程语言它也可以用在图形图像驱动编程、移动应用程序开发
和机器学习等诸多领域。目前Go语言已经成为受欢迎的作为无类型的脚本语言的替代者
因为Go编写的程序通常比脚本语言运行的更快也更安全而且很少会发生意外的类型错误。
![](../images/ch0-01.png)
Go语言还是一个开源的项目,可以免费获取编译器、库、配套工具的源代码
Go语言的贡献者来自一个活跃的全球社区。Go语言可以运行在类[UNIX](http://doc.cat-v.org/unix/)系统——
比如[Linux](http://www.linux.org/)、[FreeBSD](https://www.freebsd.org/)、[OpenBSD](http://www.openbsd.org/)、[Mac OSX](http://www.apple.com/cn/osx/)——和[Plan9](http://plan9.bell-labs.com/plan9/)系统和[Microsoft Windows](https://www.microsoft.com/zh-cn/windows/)操作系统之上。
Go语言编写的程序无需修改就可以运行在上面这些环境。
Go语言有时候被描述为“C类似语言”或者是“21世纪的C语言”。Go从C语言继承了相似的表达式语法、控制流结构、基础数据类型、调用参数传值、指针等很多思想还有C语言一直所看中的编译后机器码的运行效率以及和现有操作系统的无缝适配
本书是为了帮助你开始以有效的方式使用Go语言充分利用语言本身的特性和自带的标准库去编写清晰地道的Go程序
但是在Go语言的家族树中还有其它的祖先。其中一个有影响力的分支来自[Niklaus Wirth](https://en.wikipedia.org/wiki/Niklaus_Wirth)所设计的[Pascal][Pascal]语言。然后[Modula-2][Modula-2]语言激发了包的概念。然后[Oberon][Oberon]语言摒弃了模块接口文件和模块实现文件之间的区别。第二代的[Oberon-2][Oberon-2]语言直接影响了包的导入和声明的语法,还有[Oberon][Oberon]语言的面向对象特性所提供的方法的声明语法等
Go语言的另一支祖先带来了Go语言区别其他语言的重要特性灵感来自于贝尔实验室的[Tony Hoare](https://en.wikipedia.org/wiki/Tony_Hoare)于1978年发表的鲜为外界所知的关于并发研究的基础文献 *顺序通信进程* *[communicating sequential processes][CSP]* ,缩写为[CSP][CSP]。在[CSP][CSP]中,程序是一组中间没有共享状态的平行运行的处理过程,它们之间使用管道进行通信和控制同步。不过[Tony Hoare](https://en.wikipedia.org/wiki/Tony_Hoare)的[CSP][CSP]只是一个用于描述并发性基本概念的描述语言,并不是一个可以编写可执行程序的通用编程语言。
接下来Rob Pike和其他人开始不断尝试将[CSP](https://en.wikipedia.org/wiki/Communicating_sequential_processes)引入实际的编程语言中。他们第一次尝试引入[CSP](https://en.wikipedia.org/wiki/Communicating_sequential_processes)特性的编程语言叫[Squeak](http://doc.cat-v.org/bell_labs/squeak/)(老鼠间交流的语言),是一个提供鼠标和键盘事件处理的编程语言,它的管道是静态创建的。然后是改进版的[Newsqueak](http://doc.cat-v.org/bell_labs/squeak/)语言提供了类似C语言语句和表达式的语法和类似[Pascal][Pascal]语言的推导语法。Newsqueak是一个带垃圾回收的纯函数式语言它再次针对键盘、鼠标和窗口事件管理。但是在Newsqueak语言中管道是动态创建的属于第一类值可以保存到变量中。
在Plan9操作系统中这些优秀的想法被吸收到了一个叫[Alef][Alef]的编程语言中。Alef试图将Newsqueak语言改造为系统编程语言但是因为缺少垃圾回收机制而导致并发编程很痛苦。译注在Alef之后还有一个叫[Limbo][Limbo]的编程语言Go语言从其中借鉴了很多特性。 具体请参考Pike的讲稿http://talks.golang.org/2012/concurrency.slide#9
Go语言的其他的一些特性零散地来自于其他一些编程语言比如iota语法是从[APL][APL]语言借鉴,词法作用域与嵌套函数来自于[Scheme][Scheme]语言和其他很多语言。当然我们也可以从Go中发现很多创新的设计。比如Go语言的切片为动态数组提供了有效的随机存取的性能这可能会让人联想到链表的底层的共享机制。还有Go语言新发明的defer语句。
## Go语言项目
所有的编程语言都反映了语言设计者对编程哲学的反思通常包括之前的语言所暴露的一些不足地方的改进。Go项目是在Google公司维护超级复杂的几个软件系统遇到的一些问题的反思但是这类问题绝不是Google公司所特有的
正如[Rob Pike](http://genius.cat-v.org/rob-pike/)所说,“软件的复杂性是乘法级相关的”,通过增加一个部分的复杂性来修复问题通常将慢慢地增加其他部分的复杂性。通过增加功能、选项和配置是修复问题的最快的途径,但是这很容易让人忘记简洁的内涵,即从长远来看,简洁依然是好软件的关键因素。
简洁的设计需要在工作开始的时候舍弃不必要的想法,并且在软件的生命周期内严格区别好的改变和坏的改变。通过足够的努力,一个好的改变可以在不破坏原有完整概念的前提下保持自适应,正如[Fred Brooks](http://www.cs.unc.edu/~brooks/)所说的“概念完整性”;而一个坏的改变则不能达到这个效果,它们仅仅是通过肤浅的和简单的妥协来破坏原有设计的一致性。只有通过简洁的设计,才能让一个系统保持稳定、安全和持续的进化。
Go项目包括编程语言本身附带了相关的工具和标准库最后但并非代表不重要的是关于简洁编程哲学的宣言。就事后诸葛的角度来看Go语言的这些地方都做的还不错拥有自动垃圾回收、一个包系统、函数作为一等公民、词法作用域、系统调用接口、只读的UTF8字符串等。但是Go语言本身只有很少的特性也不太可能添加太多的特性。例如它没有隐式的数值转换没有构造函数和析构函数没有运算符重载没有默认参数也没有继承没有泛型没有异常没有宏没有函数修饰更没有线程局部存储。但是语言本身是成熟和稳定的而且承诺保证向后兼容用之前的Go语言编写程序可以用新版本的Go语言编译器和标准库直接构建而不需要修改代码。
Go语言有足够的类型系统以避免动态语言中那些粗心的类型错误但是Go语言的类型系统相比传统的强类型语言又要简洁很多。虽然有时候这会导致一个“无类型”的抽象类型概念但是Go语言程序员并不需要像C++或Haskell程序员那样纠结于具体类型的安全属性。在实践中Go语言简洁的类型系统给程序员带来了更多的安全性和更好的运行时性能。
Go语言鼓励当代计算机系统设计的原则特别是局部的重要性。它的内置数据类型和大多数的准库数据结构都经过精心设计而避免显式的初始化或隐式的构造函数因为很少的内存分配和内存初始化代码被隐藏在库代码中了。Go语言的聚合类型结构体和数组可以直接操作它们的元素只需要更少的存储空间、更少的内存写操作而且指针操作比其他间接操作的语言也更有效率。由于现代计算机是一个并行的机器Go语言提供了基于CSP的并发特性支持。Go语言的动态栈使得轻量级线程goroutine的初始栈可以很小因此创建一个goroutine的代价很小创建百万级的goroutine完全是可行的。
Go语言的标准库通常被称为语言自带的电池提供了清晰的构建模块和公共接口包含I/O操作、文本处理、图像、密码学、网络和分布式应用程序等并支持许多标准化的文件格式和编解码协议。库和工具使用了大量的约定来减少额外的配置和解释从而最终简化程序的逻辑而且每个Go程序结构都是如此的相似因此Go程序也很容易学习。使用Go语言自带工具构建Go语言项目只需要使用文件名和标识符名称一个偶尔的特殊注释来确定所有的库、可执行文件、测试、基准测试、例子、以及特定于平台的变量、项目的文档等Go语言源代码本身就包含了构建规范。
## 本书的组织
我们假设你已经有一种或多种其他编程语言的使用经历不管是类似C、C++或Java的编译型语言还是类似Python、Ruby、JavaScript的脚本语言因此我们不会像对完全的编程语言初学者那样解释所有的细节。因为Go语言的变量、常量、表达式、控制流和函数等基本语法也是类似的。
第一章包含了本教程的基本结构通过十几个程序介绍了用Go语言如何实现类似读写文件、文本格式化、创建图像、网络客户端和服务器通讯等日常工作。
第二章描述了Go语言程序的基本元素结构、变量、新类型定义、包和文件、以及作用域等概念。第三章讨论了数字、布尔值、字符串和常量并演示了如何显示和处理Unicode字符。第四章描述了复合类型从简单的数组、字典、切片到动态列表。第五章涵盖了函数并讨论了错误处理、panic和recover还有defer语句。
第一章到第五章是基础部分主流命令式编程语言这部分都类似。个别之处Go语言有自己特色的语法和风格但是大多数程序员能很快适应。其余章节是Go语言特有的方法、接口、并发、包、测试和反射等语言特性。
Go语言的面向对象机制与一般语言不同。它没有类层次结构甚至可以说没有类仅仅通过组合而不是继承简单的对象来构建复杂的对象。方法不仅可以定义在结构体上而且可以定义在任何用户自定义的类型上并且具体类型和抽象类型接口之间的关系是隐式的所以很多类型的设计者可能并不知道该类型到底实现了哪些接口。方法在第六章讨论接口在第七章讨论。
第八章讨论了基于顺序通信进程CSP概念的并发编程使用goroutines和channels处理并发编程。第九章则讨论了传统的基于共享变量的并发编程。
第十章描述了包机制和包的组织结构。这一章还展示了如何有效地利用Go自带的工具使用单个命令完成编译、测试、基准测试、代码格式化、文档以及其他诸多任务。
第十一章讨论了单元测试Go语言的工具和标准库中集成了轻量级的测试功能避免了强大但复杂的测试框架。测试库提供了一些基本构件必要时可以用来构建复杂的测试构件。
第十二章讨论了反射一种程序在运行期间审视自己的能力。反射是一个强大的编程工具不过要谨慎地使用这一章利用反射机制实现一些重要的Go语言库函数展示了反射的强大用法。第十三章解释了底层编程的细节在必要时可以使用unsafe包绕过Go语言安全的类型系统。
每一章都有一些练习题你可以用来测试你对Go的理解你也可以探讨书中这些例子的扩展和替代。
书中所有的代码都可以从 http://gopl.io 上的Git仓库下载。go get命令根据每个例子的导入路径智能地获取、构建并安装。只需要选择一个目录作为工作空间然后将GOPATH环境变量设置为该路径。
必要时Go语言工具会创建目录。例如
```
$ export GOPATH=$HOME/gobook # 选择工作目录
$ go get gopl.io/ch1/helloworld # 获取/编译/安装
$ $GOPATH/bin/helloworld # 运行程序
Hello, 世界 # 这是中文
```
运行这些例子需要安装Go1.5以上的版本。
```
$ go version
go version go1.5 linux/amd64
```
如果使用其他的操作系统,请参考 https://golang.org/doc/install 提供的说明安装。
## 更多的信息
最佳的帮助信息来自Go语言的官方网站https://golang.org 它提供了完善的参考文档包括编程语言规范和标准库等诸多权威的帮助信息。同时也包含了如何编写更地道的Go程序的基本教程还有各种各样的在线文本资源和视频资源它们是本书最有价值的补充。Go语言的官方博客 https://blog.golang.org 会不定期发布一些Go语言最好的实践文章包括当前语言的发展状态、未来的计划、会议报告和Go语言相关的各种会议的主题等信息译注 http://talks.golang.org/ 包含了官方收录的各种报告的讲稿)。
在线访问的一个有价值的地方是可以从web页面运行Go语言的程序而纸质书则没有这么便利了。这个功能由来自 https://play.golang.org 的 Go Playground 提供,并且可以方便地嵌入到其他页面中,例如 https://golang.org 的主页,或 godoc 提供的文档页面中。
Playground可以简单的通过执行一个小程序来测试对语法、语义和对程序库的理解类似其他很多语言提供的REPL即时运行的工具。同时它可以生成对应的url非常适合共享Go语言代码片段汇报bug或提供反馈意见等。
基于 Playground 构建的 Go Tourhttps://tour.golang.org 是一个系列的Go语言入门教程它包含了诸多基本概念和结构相关的并可在线运行的互动小程序。
当然Playground 和 Tour 也有一些限制它们只能导入标准库而且因为安全的原因对一些网络库做了限制。如果要在编译和运行时需要访问互联网对于一些更复杂的实验你可能需要在自己的电脑上构建并运行程序。幸运的是下载Go语言的过程很简单从 https://golang.org 下载安装包应该不超过几分钟译注感谢伟大的长城让大陆的Gopher们都学会了自己打洞的基本生活技能下载时间可能会因为洞的大小等因素从几分钟到几天或更久然后就可以在自己电脑上编写和运行Go程序了。
Go语言是一个开源项目你可以在 https://golang.org/pkg 阅读标准库中任意函数和类型的实现代码,和下载安装包的代码完全一致。这样,你可以知道很多函数是如何工作的, 通过挖掘找出一些答案的细节或者仅仅是出于欣赏专业级Go代码。
## 致谢
[Rob Pike](http://genius.cat-v.org/rob-pike/)和[Russ Cox](http://research.swtch.com/)以及很多其他Go团队的核心成员多次仔细阅读了本书的手稿他们对本书的组织结构和表述用词等给出了很多宝贵的建议。在准备日文版翻译的时候Yoshiki Shibata更是仔细地审阅了本书的每个部分及时发现了诸多英文和代码的错误。我们非常感谢本书的每一位审阅者并感谢对本书给出了重要的建议的Brian Goetz、Corey Kosak、Arnold Robbins、Josh Bleecher Snyder和Peter Weinberger等人。
我们还感谢Sameer Ajmani、Ittai Balaban、David Crawshaw、Billy Donohue、Jonathan Feinberg、Andrew Gerrand、Robert Griesemer、John Linderman、Minux Ma译注中国人Go团队成员。、Bryan Mills、Bala Natarajan、Cosmos Nicolaou、Paul Staniforth、Nigel Tao译注好像是陶哲轩的兄弟以及Howard Trickey给出的许多有价值的建议。我们还要感谢David Brailsford和Raph Levien关于类型设置的建议。
我们从来自Addison-Wesley的编辑Greg Doench收到了很多帮助从最开始就得到了越来越多的帮助。来自AW生产团队的John Fuller、Dayna Isley、Julie Nahil、Chuti Prasertsith到Barbara Wood感谢你们的热心帮助。
[Alan Donovan](https://github.com/adonovan)特别感谢Sameer Ajmani、Chris Demetriou、Walt Drummond和Google公司的Reid Tatge允许他有充裕的时间去写本书感谢Stephen Donovan的建议和始终如一的鼓励以及他的妻子Leila Kazemi并没有让他为了家庭琐事而分心并热情坚定地支持这个项目。
[Brian Kernighan](http://www.cs.princeton.edu/~bwk/)特别感谢朋友和同事对他的耐心和宽容让他慢慢地梳理本书的写作思路。同时感谢他的妻子Meg和其他很多朋友对他写作事业的支持。
2015年 10月 于 纽约
{% include "./links.md" %}