[套装书]Head First Go语言程序设计+Go程序设计语言(2册)

作者
杰伊·麦克格瑞恩 艾伦A. A.多诺万 布莱恩W.柯尼汉
丛书名
O’Reilly精品图书系列
出版社
机械工业出版社
ISBN
9782009221618
简要
简介
内容简介书籍计算机书籍 ---------------------------Head First Go语言程序设计--------------------------- Go是为高性能网络和多处理而设计的, 但与python和javascript一样,该语言易于阅读和使用。通过这本实用的实践指南,读者将学习如何使用演示实际语言的清晰示例来编写Go代码。最重要的是,读者将会了解到用人单位希望入门级Go开发人员所知晓的惯例和技术。主要内容包括语法基础、条件和循环、函数、包、数组、映射、结构、封装和嵌入、接口、故障恢复、共享、自动化测试、Web应用程序等。 ---------------------------Go程序设计语言--------------------------- 本书由《C程序设计语言》的作者Kernighan和谷歌公司Go团队主管Alan Donovan联袂撰写,是学习Go语言程序设计的权威指南。本书共13章,主要内容包括:Go的基础知识、基本结构、基本数据类型、复合数据类型、函数、方法、接口、goroutine、通道、共享变量的并发性、包、go工具、测试、反射等。 本书适合作为计算机相关专业的教材,也可供Go语言爱好者阅读。
目录



---------------------------Head First Go语言程序设计---------------------------


(概要)
如何使用这本书:前言 xxvii
1 让我们开始吧:语法基础 1
2 接下来运行哪些代码:条件和循环 31
3 调用:函数 79
4 代码集:包 113
5 列表:数组 149
6 追加的问题:切片 175
7 标签数据:映射 205
8 构建存储:struct 231
9 我喜欢的类型:定义类型 265
10 保密:封装和嵌入 289
11 你能做什么:接口 321
12 重新站起来:从失败中恢复 349
13 分享工作:goroutine和 channel 379
14 代码的质量保证:自动化测试 401
15 响应请求:Web应用程序 425
16 要遵循的模式:HTML模板 445
A 理解os.OpenFile:打开文件 481
B 有六件事我们没有涉及:剩下的内容 495
(真正的)
如何使用这本书
前言
你的大脑如何看待Go。在这里,你试图学习一些东西,而你的大脑 在帮你的忙,确保学习不会停滞不前。你的大脑在想:“最好给更重要的 事情留点儿空间,比如避开哪些野生动物,裸体滑雪是否是个坏主意。” 那么,你如何欺骗你的大脑,让它认为你的生活依赖于如何用Go编程呢
这本书是给谁看的 xxviii
我们知道你在想什么 xxix
我们知道你的大脑在想什么 xxix
元认知:思考“何为思考” xxxi
我们是这样做的 xxxii
说明 xxxiv
致谢 xxxv
1让我们开始吧 语法基础
准备好给你的软件充电了吗你想要一种编译速度快的简单编程语言吗它跑 得快吗它可以很容易地将你的工作分发给用户吗那就准备好学习Go吧!
Go是一种注重简单性和速度的编程语言。它比其他语言都简单,所以学起来更快。它 可以让你利用当今多核计算机处理器的能力,使你的程序运行得更快。本章将向你展 示所有Go的功能,这些功能将使你作为开发人员的生活更轻松,并使你的用户更快乐。
准备好,出发 2
Go Playground 3
这一切意味着什么 4
如果出了问题怎么办 5
调用函数 7
Println函数 7
使用其他包中的函数 8
函数返回值 9
Go程序模板 11
字符串 11
符文 12
布尔值 12
数字 13
数学运算与比较 13
类型 14
声明变量 16
零值 17
短变量声明 19
命名规则 21
转换 22
在你的计算机上安装Go 25
编译Go代码 26
Go工具 27
使用“go run”快速尝试代码 27
你的Go 工具箱 28
package main import fmt func main() {
}
fmt.Println( )
Hello, Go!
Hello, Go!
1+ 2
true
3
4 viii
'?'
1174 输出
2 接下来运行哪些代码
条件和循环
每个程序都有仅在特定情况下适用的部分。“如果出现错误,应该运行 这段代码。否则,应该运行其他代码。”几乎每个程序都包含只有在特定条件为真时才 应该运行的代码。因此,几乎每种编程语言都提供条件语句,让你决定是否运行某段代 码。Go也不例外。
你可能还需要重复运行代码中的某些部分。与大多数语言一样,Go提供了循环, 可以多次运行某部分代码。在本章中,我们将学习使用条件句和循环!
调用方法 32
评分 34
函数或方法的多个返回值 36
选项1:使用空白标识符忽略错误返回值 37
选项2:处理错误 38
条件 39
有条件地记录致命错误 42
避免遮盖名字 44
将字符串转换为数字 46
块 49
块和变量的作用域 50
我们已经完成了评分程序 52
短变量声明中只有一个变量必须是新的 54
让我们创建一个游戏 55
包名与导入路径 56
生成随机数 57
从键盘获取整数 59
将猜测与目标进行比较 60
循环 61
初始化和标志(post)语句是可选的 63
在我们的猜谜游戏中使用循环 66
中断我们的猜测循环 69
显示目标 70
恭喜你,游戏结束了 72
你的Go工具箱 74
条件语句块 结束
条件语句块 开始
条件语句块主体
“if”关键字
条件
if 1fmt.Println(It's true!)
}
3 调用
函数
你错过了机会。你一直像专业人士一样调用函数。但你唯一能调用的函数是 Go为你定义的函数。现在,轮到你了。我们将向你展示如何创建你自己的函数。 我们将学习如何声明带参数和不带参数的函数。我们将声明返回单个值的函数, 并且我们将学习如何返回多个值,以便我们可以指示何时发生了错误。我们还将 学习指针,它允许我们进行更有效的内存函数的调用。
一些重复的代码 80
使用Printf和Sprintf格式化输出 81
格式化动词 82
格式化值宽度 83
格式化小数宽度 84
在油漆计算器中使用Printf 85
声明函数 86
声明函数参数 87
在油漆计算器中使用函数 88
函数和变量的作用域 90
函数返回值 91
在油漆计算器中使用返回值 93
paintNeeded函数需要错误处理 95
错误值 96
声明多个返回值 97
在paintNeeded函数中使用多个返回值 98
始终处理错误 99
函数形参接收实参的副本 102
指针 103
指针类型 104
获取或更改指针的值 105
函数指针 107
使用指针修复我们的“double”函数 108
你的Go工具箱 110
4 代码集

是时候整理一下了。到目前为止,我们一直将所有代码放在一个文件中。 随着我们的程序变得越来越大、越来越复杂,这很快就会变得一团糟。
在本章中,我们将向你展示如何创建自己的包,以帮助将相关代码集中放在 一个地方。但是包不仅仅对组织结构有益,它还是在程序之间共享代码的一种简单方法,同时也是与其他开发人员共享代码的一种简单方法。
不同的程序,相同的函数 114
使用包在程序之间共享代码 116
Go工作区保存包代码 117
创建一个新包 118
将包导入程序 119
包使用相同的文件布局 120
包命名规范 123
包限定符 123
将共享代码移动到包中 124
常量 126
嵌套的包和导入路径 128
使用“go install”安装程序可执行文件 130
使用GOPATH环境变量更改工作区 131
设置GOPATH 132
发布包 133
使用“go get”下载和安装包 137
使用“go doc”阅读包文档 139
使用doc注释记录包 141
在Web浏览器中查看文档 143
使用“godoc”提供HTML文档 144
“godoc”服务器包含你的包 145
你的Go工具箱 146
go
bin
hi pkg
src
greeting
greeting.go hi
main.go
5 列表
数组
很多程序都处理列表。地址列表、电话号码列表、产品列表。Go有两种内置 的存储列表的方法。本章将介绍第一种:数组。你将了解如何创建数组,如何用数 据填充数组,以及如何重新获取这些数据。然后你将学习如何处理数组中的所有元 素,首先是使用for循环的困难些的方法,然后是使用for...range循环的简单 些的方法。
数组保存值的集合 150
数组中的零值 152
数组字面量 153
“fmt”包中的函数知道如何处理数组 154
在循环里访问数组元素 155
使用“len”函数检查数组长度 156
使用“for ... range”安全遍历数组 157
在“for ... range”循环中使用空白标识符 158
得到数组中数字之和 159
得到数组中数字的平均值 161
读取文本文件 163
将文本文件读入数组 166
更新我们的“average”程序来读取文本文件 168
我们的程序只能处理三个值 170
你的Go工具箱 172
数组中将要存储的元素类型
数组中将要存储的元素个数
var myArray [4]string
索引0
索引1
索引2
索引3
6 追加的问题
切片
我们已经知道了无法将更多的元素增加到一个数组中。对于程序的确是个问题。因为我们无法提前知道文件中包含多少个块。而这就是Go中的切片 (slice)的用武之地。切片是一个可以通过增长来保存额外数据的集合类型,正好能够满足程序的需要!我们将看到切片是如何让用户以简洁的方式在程序中提供 数据的,以及如何帮助你写出更加方便调用的函数。
切片 176
切片字面量 177
切片运算符 180
底层数组 182
修改底层数组,修改切片 183
使用“append”函数在切片上添加数据 184
切片和零值 186
使用切片和“append”读取额外的文件行 187
尝试我们改进后的程序 189
出错时返回nil值切片 190
命令行参数 191
从os.Args切片获取命令行参数 192
切片运算符可用于其他切片 193
更新程序以使用命令行参数 194
可变长参数函数 195
使用可变长参数函数 197
使用可变长参数函数计算平均值 198
向可变长参数函数传递一个切片 199
切片拯救了我们 201
你的Go工具箱 202
切片
底层数组
数组1
切片1
{a, b, c, d, e}
7 标签数据
映射
堆积物品是个好方法,直到你需要再次找到它。你已经看到了如何使用 切片和数组来创建一列数据。但是当你需要使用一个特定的值时会怎样为了找 到它,你需要从数组或者切片的开头开始,查看每一个元素。
如果有一种集合,其中的每个值都有个标签在上面,那么你就可以快速找到你需 要的值!在这一章,我们来看映射,它就是做这个的。
计票 206
从文件中读取名字 207
使用困难的切片方法对名字计数 209
映射 212
映射字面量 214
映射中的零值 215
映射变量的零值是nil 215
如何区分已经赋值的值和零值 216
使用“delete”函数删除键/值对 218
使用映射来更新计票程序 219
对映射进行for ... range循环 221
for ... range循环以随机顺序处理映射 223
使用for ... range循环来更新计票程序 224
计票程序完成 225
你的Go工具箱 227
Carlos Diaz
Amber Graham Brian Martin
Mikey Moose
键可以使你快速 找到数据!
8 构建存储
struct
有时你需要保存超过一种类型的数据。我们学习了切片,它能够保存 一组数据。然后学习了映射,它能保存一组键和一组值。这两种数据结构都只 能保存一种类型。有时,你需要一组不同类型的数据,例如邮件地址,混合了 街道名(字符串类型)和邮政编码(整型);又如学生记录,混合保存学生名 字和成绩(浮点数)。你无法用切片或者映射来保存。但是你可以使用其他的名为struct的类型来保存。本章会介绍struct的所有信息!
切片和映射保存一种类型的值 232
struct是由多种类型的值构建的 233
使用点运算符访问struct字段 234
在struct中保存订阅者的数据 235
定义类型和struct 236
为杂志订阅者定义一个类型 238
与函数一起使用已定义类型 239
使用函数修改struct 242
通过指针访问struct的字段 244
使用指针传递大型struct 246
将struct类型移动到另一个包 248
定义类型的名称首字母必须大写才能导出该类型 249
struct字段的名称首字母必须大写才能导出该字段 250
struct字面量 251
创建一个Employee struct类型 253
创建一个Address struct类型 254
将struct作为字段增加到另一个类型中 255
在另一个struct中设置struct 255
匿名struct字段 258
嵌入struct 259
我们定义的类型完成了 260
你的Go工具箱 261
9 我喜欢的类型
定义类型
定义类型还有更多内容需要学习。在之前的章节,我们展示了如何使用 strcut基础类型来定义类型。没有展示如何使用任意类型作为基础类型。
但是你记得方法——与特定值类型关联的特殊的函数吗我们在整本书中都在调 用多种值的方法,但是没有展示如何定义自己的方法。在本章中,我们打算介 绍。让我们开始吧!
现实生活中的类型错误 266
具有底层基础类型的定义类型 267
定义类型和运算符 269
使用函数进行类型转换 271
使用方法修复函数名冲突 274
定义方法 275
接收器参数(几乎)就是另一个参数 276
方法(几乎)就像一个函数 277
指针类型的接收器参数 279
使用方法将Liters和Milliliters转换为Gallons 283
使用方法将Gallons转换为Liters和Milliliters 284
你的Go工具箱 285
Steve认为他 买了多少。
Steve实际上 买了多少!
10 加仑
10 升
10 保密
封装和嵌入
错误总会发生。有时,你的程序会接收到无效的数据,从用户输入、从文件读取或以其他方式。在本章,你会学到封装:一个保护struct字段免受无效数据的 方法。这样,你的数据字段能够安全地使用。
我们也会在你的类型内部嵌入其他的类型。如果你的struct类型需要已经存在 于其他类型的方法,你不需要拷贝粘贴方法代码。你可以将其他类型嵌入你的 struct类型中,然后像使用你自己的类型的定义方法一样使用嵌入类型的方法!
创建一个日期struct类型 290
人们将Date struct的字段设置为无效值 291
setter方法 292
setter方法需要指针接收器 293
添加其余的setter方法 294
在setter方法中添加校验 296
字段仍可以设置为无效值 298
将Date类型移到另外的包中 299
将Date字段设为未导出状态 301
通过导出的方法访问未导出的字段 302
getter方法 304
封装 305
在Event类型中嵌入Date类型 308
未导出的字段不会被提升 309
导出的方法像字段一样被提升 310
封装Event的Title字段 312
提升的方法与外部类型的方法共存 313
我们的calendar包完成了 314
你的Go工具箱 316
当人们实际使用setter方法时,它们提供的校验非常 棒。但是我们已经让人们直接设置struct字段,他们 仍然在输入无效数据!
11 你能做什么
接口
有时你并不关心一个值的特定类型。你不需要关心它是什么。你只需要 知道它能做特定的事情。你能够在其上调用特定的接口。不需要关心是pen还是 pencil,你仅仅需要一个Draw方法。不需要关心是Car还是Boat,你只需要一个 Steer方法。
那就是Go接口的目标。它允许你定义能够保存任何类型的变量和函数参数,前提 是它定义了特定的方法。
具有相同方法的两种不同类型 322
只能接受一种类型的方法参数 323
接口 325
定义满足接口的类型 326
具体类型和接口类型 327
分配满足接口的任何类型 328
你只能调用接口中定义的方法 329
使用接口修复playList函数 331
类型断言 334
类型断言失败 336
当类型断言失败时避免异常 337
使用类型断言测试TapePlayer和TapeRecorder 338
“error”接口 340
Stringer接口 342
空接口 344
你的Go工具箱 347
播放器 录音机
12 重新站起来
从失败中恢复
每个程序都会遇到错误,你应该为它们做好计划。有时候,处理错误 可以像报告错误并退出程序一样简单。但是其他错误可能需要额外的操作。你可 能需要关闭打开的文件或网络连接,或者以其他方式清理,这样你的程序就不会 留下混乱。在本章中,我们将向你展示如何延迟清理操作,以便在出现错误时也 能执行这些操作。我们还将向你展示如何在适当的(罕见的)情况下使程序出现panic,以及如何在事后恢复。
从文件中读取数字,重新访问 350
任何错误都将阻止关闭文件 352
延迟函数调用 353
使用延迟函数调用从错误中恢复 354
使用延迟函数调用确保文件关闭 355
列出中的文件 358
列出子中的文件(会更棘手) 359
递归函数调用 360
递归地列出内容 362
递归函数中的错误处理 364
发起一个panic 365
堆栈跟踪 366
延迟调用在崩溃前完成 366
通过scanDirectory 使用“panic” 367
何时产生panic 368
“recover”函数 370
panic值从recover中返回 371
从scanDirectory中的panic恢复 373
恢复panic 374
你的Go工具箱 376
不能转换成 float64类型!
20.25
hello
10.5
bad-data.txt
13 分享工作
goroutine和channel
一次只做一件事并不总是完成任务最快的方法。一些大问题可以分解 成小任务。goroutine可以让程序同时处理几个不同的任务。goroutine可以使用 channel来协调它们的工作,channel允许goroutine互相发送数据并同步,这样一 个goroutine就不会领先于另一个goroutine。goroutine让你充分利用具有多处理 器的计算机,让程序运行得尽可能快!
检索网页 380
多任务 382
使用goroutine的并发性 383
使用goroutine 384
在responseSize函数中使用goroutine 386
我们不能直接控制goroutine何时运行 388
go语句不能使用返回值 389
使用channel发送和接收值 391
同步goroutine与channel 392
观察goroutine同步 393
使用channel修复我们的网页大小程序 396
更新我们的channel以携带一个struct 398
你的Go工具箱 399
接收端goroutine等待另一个 goroutine的发送值。
14 代码的质量保证
自动化测试
你确定你的软件工作良好吗真的确定吗 在将新版本发给用户之前, 你可能已经尝试了新特性,以确保它们都能正常工作。但你有没有尝试过旧的 特性,以确保你没有破坏它们中的任何一个所有的旧特性如果这个问题让你担 心,那么你的程序需要自动化测试。自动化测试确保程序的组件能够正确工作, 即使在你更改代码之后也是如此。Go的testing包和go test工具使用你已经学 习的技能,使编写自动化测试变得更加容易!
自动化测试比别人先发现bug 402
一个应该有自动化测试的函数 403
我们引入了一个bug 405
编写测试 406 使用“go test”命令运行测试 407
测试实际的返回值 408
使用“Errorf”方法获得更详细的测试失败消息 410
测试“helper”函数 411
让测试通过 412
测试驱动开发 413
另一个需要修复的bug 414
运行特定的测试集 417
表驱动测试 418
使用测试修复panic代码 420
你的Go工具箱 422
通过。 对于 []slice{apple, orange, pear}, JoinWithCommas 应返回 apple, orange, and pear。
失败! 对于 []slice{apple, orange}, JoinWithCommas 应返回 apple and orange。
15 响应请求
Web应用程序
这是21世纪。用户需要Web应用程序。Go在这里已经覆盖了!Go标准库包 含一些包,可以帮助你托管自己的Web应用程序,并使它们可以从任何Web浏览器 访问。因此,我们将在本书的最后两章向你展示如何构建Web应用程序。
Web应用程序需要做的第一件事是当浏览器向它发送请求时能够做出响应。在本章 中,我们将学习如何使用net/http包来实现这一点。
用Go编写Web应用程序 426
浏览器、请求、服务器和响应 427
一个简单的Web应用程序 428
你的计算机在自言自语 429
讲解一个简单的Web应用程序 430
资源路径 432
对不同的资源路径做出不同的响应 433
一级函数 435
将函数传递给其他函数 436
函数作为类型 436
接下来是什么 440
你的Go工具箱 441
example.com:
GET /hello
GET /hello
Hello, web!
example.com
你的Go程序
Hello, web!
16 要遵循的模式
HTML模板
你的Web应用程序需要用HTML而不是纯文本进行响应。纯文本可以 用于电子邮件和社交媒体帖子。但是你的页面需要格式化。它们需要标题和段落。 它们需要用户可以向你的应用程序提交数据的表单。要做到这一点,你需要HTML代码。
最后,你需要将数据插入HTML代码中。这就是Go提供html/template包的原因, 这是一种在应用程序的HTML响应中包含数据的强大方法。模板是构建更大、更好的Web应用程序的关键,在这最后的一章里,我们将向你展示如何使用它们!
留言簿应用程序 446
处理请求和检查错误的函数 447
设置一个项目并尝试应用程序 448
用HTML创建签名列表 449
使我们的应用程序以HTML响应 450
“text/template”包 451
使用带有模板的Execute方法的io.Writer接口 452
满足io.Writer的ResponseWriter和os.Stdout 453
使用action将数据插入模板 454
使用“if”action使模板的某些部分可选 455
使用“range”action来重复模板的某部分 456
使用action将struct字段插入模板 457
从文件中读入签名切片 458
保存签名和签名数的struct 460
更新模板以包含签名 461
允许用户使用HTML表单添加数据 464
表单提交请求 466
用于表单提交的Path和HTTP方法 467
从请求中获取表单字段的值 468
保存表单数据 470
HTTP重定向 472
我们完整的应用程序代码 474
你的Go工具箱 477
响应主留言簿页面的请求。
使用HTML格式化响应。
使用签名填充HTML页面。
设置用于添加新签名的 表单。
保存提交的签名。
A 理解os.OpenFile
打开文件
有些程序需要将数据写入文件,而不仅仅是读取数据。在整本书中, 当我们想要处理文件时,必须在文本编辑器中创建它们,以便程序读取。但是有 些程序生成数据,当生成数据时,程序需要能够将数据写入文件。
在本书的前面,我们使用os.OpenFile函数打开一个文件,以便写入。但我们当 时没有足够的空间来充分探索它是如何工作的。在本附录中,我们将向你展示有 效使用os.OpenFile所需的所有知识!
理解os.OpenFile 482
将标志常量传递到os.OpenFile 483
二进制表示法 485
位运算符 485
按位与运算符 486
按位或运算符 487
对“os”包常量使用按位或运算 488
使用按位或运算修复os.OpenFile选项 489
Unix样式的文件权限 490
使用os.FileMode类型表示权限 491
八进制表示法 492
将八进制值转换为FileMode值 493
解释对os.OpenFile的调用 494
这次将把新文本 追加到文件中。
Aardvarks are...
amazing!
aardvark.txt
B 有六件事我们没有涉及
剩下的内容
我们已经讲了很多内容,你几乎看完了这本书。我们会想念你的,但在 让你离开之前,如果不多做一点准备就把你送到这个世界上去,我们会觉得不太 合适。我们为本附录保存了六个重要的主题。
#1 “if”的初始化语句 496
#2 switch语句 498
#3 更多基本类型 499
#4 更多关于符文的信息 499
#5 有缓冲的channel 503
#6 进一步阅读 506
初始化语句
条件
if count := 5; count > 4 {
fmt.Println(count is, count)
}
0: A 1: B 2: C 3: D 4: E 0: Б 2: Г 4: Д 6: Ж 8: И
d
c
b
a
额外发送的值将添加到缓冲 区中,直到缓冲区满为止。
所有字符都是可打印的。
当缓冲区已满时发送一个值会导致发送goroutine的阻塞。



---------------------------Go程序设计语言---------------------------


出版者的话
译者序
前言
第1章 入门 1
1.1 hello,world 1
1.2 命令行参数 3
1.3 找出重复行 6
1.4 GIF动画 10
1.5 获取一个URL 12
1.6 并发获取多个URL 13
1.7 一个Web服务器 14
1.8 其他内容 17
第2章 程序结构 20
2.1 名称 20
2.2 声明 21
2.3 变量 22
2.3.1 短变量声明 22
2.3.2 指针 23
2.3.3 new函数 25
2.3.4 变量的生命周期 26
2.4 赋值 27
2.4.1 多重赋值 27
2.4.2 可赋值性 28
2.5 类型声明 29
2.6 包和文件 30
2.6.1 导入 31
2.6.2 包初始化 33
2.7 作用域 34
第3章 基本数据 38
3.1 整数 38
3.2 浮点数 42
3.3 复数 45
3.4 布尔值 47
3.5 字符串 47
3.5.1 字符串字面量 49
3.5.2 Unicode 49
3.5.3 UTF-8 50
3.5.4 字符串和字节slice 53
3.5.5 字符串和数字的相互转换 56
3.6 常量 56
3.6.1 常量生成器iota 57
3.6.2 无类型常量 59
第4章 复合数据类型 61
4.1 数组 61
4.2 slice 63
4.2.1 append函数 66
4.2.2 slice就地修改 69
4.3 map 71
4.4 结构体 76
4.4.1 结构体字面量 78
4.4.2 结构体比较 80
4.4.3 结构体嵌套和匿名成员 80
4.5 JSON 82
4.6 文本和HTML模板 87
第5章 函数 92
5.1 函数声明 92
5.2 递归 93
5.3 多返回值 96
5.4 错误 98
5.4.1 错误处理策略 99
5.4.2 文件结束标识 101
5.5 函数变量 102
5.6 匿名函数 104
5.7 变长函数 110
5.8 延迟函数调用 111
5.9 宕机 115
5.10 恢复 118
第6章 方法 120
6.1 方法声明 120
6.2 指针接收者的方法 122
6.3 通过结构体内嵌组成类型 124
6.4 方法变量与表达式 127
6.5 示例:位向量 128
6.6 封装 130
第7章 接口 133
7.1 接口即约定 133
7.2 接口类型 135
7.3 实现接口 136
7.4 使用flag.Value来解析参数 139
7.5 接口值 141
7.6 使用sort.Interface来排序 144
7.7 http.Handler接口 148
7.8 error接口 152
7.9 示例:表达式求值器 154
7.10 类型断言 160
7.11 使用类型断言来识别错误 161
7.12 通过接口类型断言来查询特性 162
7.13 类型分支 164
7.14 示例:基于标记的XML解析 166
7.15 一些建议 168
第8章 goroutine和通道 170
8.1 goroutine 170
8.2 示例:并发时钟服务器 171
8.3 示例:并发回声服务器 174
8.4 通道 176
8.4.1 无缓冲通道 177
8.4.2 管道 178
8.4.3 单向通道类型 180
8.4.4 缓冲通道 181
8.5 并行循环 183
8.6 示例:并发的Web爬虫 187
8.7 使用select多路复用 190
8.8 示例:并发遍历 192
8.9 取消 195
8.10 示例:聊天服务器 198
第9章 使用共享变量实现并发 201
9.1 竞态 201
9.2 互斥锁:sync.Mutex 205
9.3 读写互斥锁:sync.RWMutex 208
9.4 内存同步 208
9.5 延迟初始化:sync.Once 210
9.6 竞态检测器 212
9.7 示例:并发非阻塞缓存 212
9.8 goroutine与线程 218
9.8.1 可增长的栈 219
9.8.2 goroutine调度 219
9.8.3 GOMAXPROCS 219
9.8.4 goroutine没有标识 220
第10章 包和go工具 221
10.1 引言 221
10.2 导入路径 221
10.3 包的声明 222
10.4 导入声明 223
10.5 空导入 223
10.6 包及其命名 225
10.7 go工具 226
10.7.1 工作空间的组织 227
10.7.2 包的下载 228
10.7.3 包的构建 229
10.7.4 包的文档化 231
10.7.5 内部包 232
10.7.6 包的查询 233
第11章 测试 235
11.1 go test工具 235
11.2 Test函数 236
11.2.1 随机测试 239
11.2.2 测试命令 240
11.2.3 白盒测试 242
11.2.4 外部测试包 245
11.2.5 编写有效测试 246
11.2.6 避免脆弱的测试 247
11.3 覆盖率 248
11.4 Benchmark函数 250
11.5 性能剖析 252
11.6 Example函数 254
第12章 反射 256
12.1 为什么使用反射 256
12.2 reflect.Type和reflect.Value 257
12.3 Display:一个递归的值显示器 259
12.4 示例:编码S表达式 263
12.5 使用reflect.Value来设置值 266
12.6 示例:解码S表达式 268
12.7 访问结构体字段标签 271
12.8 显示类型的方法 273
12.9 注意事项 274
第13章 低级编程 276
13.1 unsafe.Sizeof、Alignof 和Offsetof 276
13.2 unsafe.Pointer 278
13.3 示例:深度相等 280
13.4 使用cgo调用C代码 282
13.5 关于安全的注意事项 286



有问题微信扫码联系

推荐

Understand China
桂ICP备20004708号-4