Go 编程语言是一个使得程序员更加有效率的开源项目。Go 是有表
达力、简洁、清晰和有效率的。它的并行机制使其很容易编写多核
和网络应用,而新的类型系统允许构建有性的模块化程序。Go
编译到机器码非常快速,同时具有便利的垃圾回收和强大的运行
时反射。它是快速的、静态类型编译语言,但是感觉上是动态类型
的,解释型语言。
1 简介 1
官方文档 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
前身. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
获得Go . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
在Windows 下获得Go . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
练习. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
答案. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2 基础 6
Hello World . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
编译和运行代码. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
本书使用的设置. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
变量、类型和保留字 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
运算符和内建函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Go 保留字. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
控制结构 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
内建函数. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
array 、slices 和map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
练习. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
答案. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3 函数 30
作用域 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
多值返回. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
命名返回值. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
延迟代码 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
变参. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
函数作为值. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
回调. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
恐慌(Panic)和恢复(Recover). . . . . . . . . . . . . . . . . . . . . . . 36
练习. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
答案. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
4 包 48
标识符 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
包的文档. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
测试包 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
常用的包 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
练习. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
答案. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
5 进阶 58
内存分配. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
定义自己的类型. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
----------------------- 页面 5-----------------------
ii Chapter: Contents
转换. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
练习. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
答案. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
6 接口 70
方法. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
接口名字 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
简短的例子. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
练习. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
答案. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
7 并发 82
更多关于channel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
练习. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
答案. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
8 通讯 90
io.Reader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
一些例子 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
命令行参数. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
执行命令 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
网络. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
练习. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
答案. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
A 版权 106
贡献者 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
许可证和版权 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
B 索引 108
C Bibliography 110
ListofFigures
1.1 Go 编年史. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2.1 array 与slice 对比 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.1 一个简单的LIFO 栈 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
6.1 使用反射去除层次关系. . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
ListofCodeExamples
2.1 Hello world . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2 Declaration with . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.3 Declaration with : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.4 Familiar types are still distinct . . . . . . . . . . . . . . . . . . . . . . . . . . 9
----------------------- 页面 6-----------------------
ListofCodeExamples iii
2.5 array 和slice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.6 Simple for loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.7 For loop with an array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.8 Fizz-Buzz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.9 Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.10 Runes in strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.11 Reverse a string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.1 函数定义 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.2 递归函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.3 局部作用域 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.4 全局作用域 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.5 当函数调用函数时的作用域. . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.6 没有defer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.7 With defer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3.8 函数符号 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3.9 带参数的函数符号 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3.10 在defer 中访问返回值 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
3.11 匿名函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
3.12 使用map 的函数作为值 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
3.13 Go 中的平均值函数. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
3.14 stack.String() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.15 有变参的函数. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.16 Go 编写的斐波那契函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
3.17 Map 函数. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
3.18 冒泡排序 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
4.1 A small package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
4.2 even 包的使用. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
4.3 even 包的测试. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
4.4 包里的Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
4.5 Push/Pop 测试 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
4.6 逆波兰计算器. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
5.1 Use of a pointer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
5.2 获取指针指向的值 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
5.3 Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
5.4 Go 中更加通用的map 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . 67
5.5 cat 程序 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
6.1 定义结构和结构的方法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
6.2 用空接口作为参数的函数. . . . . . . . . . . . . . . . . . . . . . . . . . . 72
6.3 实现接口失败. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
6.4 扩展内建类型错误 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
6.5 扩展非本地类型错误. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
6.6 使用反射自省. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
6.7 反射类型和值. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
6.8 私有成员的反射 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
6.9 公有成员的反射 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
6.10 通用的计算最大值 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
7.1 Go routine 实践 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
7.2 Go routines 和channel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
7.3 使用select . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
7.4 Go 的channel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
----------------------- 页面 7-----------------------
iv Chapter: Contents
7.5 添加额外的退出channel . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
7.6 Go 的斐波那契函数. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
8.1 从文件读取(无缓冲) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
8.2 从文件读取(缓冲). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
8.3 Processes in Perl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
8.6 uniq(1) 的Perl 实现 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
8.4 Go 中的进程. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
8.5 wc(1) 的Go 实现. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
8.7 uniq(1) 的Go 实现. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
8.8 一个Go quine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
8.9 简易echo 服务器 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
8.10 数字游戏 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
8.11 finger 守护进程 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
ListofExercises
1 (1) 文档. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2 (0) For-loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3 (0) FizzBuzz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4 (1) Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
5 (1) Average . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
6 (0) 平均值 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
7 (0) 整数顺序. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
8 (1) 作用域 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
9 (1) 栈 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
10 (1) 变参. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
11 (1) 斐波那契. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
12 (1) Map function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
13 (0) 最小值和最大值. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
14 (1) 冒泡排序. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
15 (1) 函数返回一个函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
16 (0) stack 包. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
17 (2) 计算器 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
18 (1) 指针运算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
19 (2) 使用interface 的map 函数 . . . . . . . . . . . . . . . . . . . . . . . . . 65
20 (1) 指针. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
21 (1) 链表. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
22 (1) Cat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
23 (2) 方法调用. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
24 (1) 接口和编译 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
25 (1) 指针和反射 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
26 (2) 接口和max() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
27 (1) Channel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
28 (2) 斐波那契II . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
29 (2) 进程. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
30 (0) 单词和字母统计. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
31 (0) Uniq . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
32 (2) Quine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
33 (1) Echo 服务. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
----------------------- 页面 8-----------------------
ListofExercises v
34 (2) 数字游戏. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
35 (1) *Finger 守护进程. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
1