diff --git a/404.html b/404.html index 4ea680e..03fef93 100644 --- a/404.html +++ b/404.html @@ -85,7 +85,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/appendix/appendix-a-errata.html b/appendix/appendix-a-errata.html index b22c59a..5640cb9 100644 --- a/appendix/appendix-a-errata.html +++ b/appendix/appendix-a-errata.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/appendix/appendix-b-author.html b/appendix/appendix-b-author.html index f0876a5..faa46f9 100644 --- a/appendix/appendix-b-author.html +++ b/appendix/appendix-b-author.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/appendix/appendix-c-cpoyright.html b/appendix/appendix-c-cpoyright.html index 8855fa2..31ac515 100644 --- a/appendix/appendix-c-cpoyright.html +++ b/appendix/appendix-c-cpoyright.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/appendix/appendix-d-translations.html b/appendix/appendix-d-translations.html index a3fbc3e..d571480 100644 --- a/appendix/appendix-d-translations.html +++ b/appendix/appendix-d-translations.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/appendix/appendix.html b/appendix/appendix.html index a8bd5d9..24e66c6 100644 --- a/appendix/appendix.html +++ b/appendix/appendix.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch1/ch1-01.html b/ch1/ch1-01.html index 51f2536..3b486c4 100644 --- a/ch1/ch1-01.html +++ b/ch1/ch1-01.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch1/ch1-02.html b/ch1/ch1-02.html index 2dd6477..6784fd0 100644 --- a/ch1/ch1-02.html +++ b/ch1/ch1-02.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch1/ch1-03.html b/ch1/ch1-03.html index 06cdd0a..abce703 100644 --- a/ch1/ch1-03.html +++ b/ch1/ch1-03.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch1/ch1-04.html b/ch1/ch1-04.html index f94dac1..91a7c80 100644 --- a/ch1/ch1-04.html +++ b/ch1/ch1-04.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch1/ch1-05.html b/ch1/ch1-05.html index 989d77c..a80d4fe 100644 --- a/ch1/ch1-05.html +++ b/ch1/ch1-05.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch1/ch1-06.html b/ch1/ch1-06.html index a90dfb1..48c778b 100644 --- a/ch1/ch1-06.html +++ b/ch1/ch1-06.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch1/ch1-07.html b/ch1/ch1-07.html index c91f00e..0bb325a 100644 --- a/ch1/ch1-07.html +++ b/ch1/ch1-07.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch1/ch1-08.html b/ch1/ch1-08.html index ccae393..a7c905a 100644 --- a/ch1/ch1-08.html +++ b/ch1/ch1-08.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch1/ch1.html b/ch1/ch1.html index d565899..052360c 100644 --- a/ch1/ch1.html +++ b/ch1/ch1.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch10/ch10-01.html b/ch10/ch10-01.html index c41437c..42e742c 100644 --- a/ch10/ch10-01.html +++ b/ch10/ch10-01.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch10/ch10-02.html b/ch10/ch10-02.html index 89fa149..9cc7c90 100644 --- a/ch10/ch10-02.html +++ b/ch10/ch10-02.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch10/ch10-03.html b/ch10/ch10-03.html index 93a460b..37a238c 100644 --- a/ch10/ch10-03.html +++ b/ch10/ch10-03.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch10/ch10-04.html b/ch10/ch10-04.html index a8cf2bc..d4dea9e 100644 --- a/ch10/ch10-04.html +++ b/ch10/ch10-04.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch10/ch10-05.html b/ch10/ch10-05.html index f41388c..d0b388e 100644 --- a/ch10/ch10-05.html +++ b/ch10/ch10-05.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch10/ch10-06.html b/ch10/ch10-06.html index cd65638..e06ea3d 100644 --- a/ch10/ch10-06.html +++ b/ch10/ch10-06.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch10/ch10-07.html b/ch10/ch10-07.html index fbc9d81..8de7ab6 100644 --- a/ch10/ch10-07.html +++ b/ch10/ch10-07.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch10/ch10.html b/ch10/ch10.html index 1aee83d..23874ec 100644 --- a/ch10/ch10.html +++ b/ch10/ch10.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch11/ch11-01.html b/ch11/ch11-01.html index 4fc3993..1187839 100644 --- a/ch11/ch11-01.html +++ b/ch11/ch11-01.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch11/ch11-02.html b/ch11/ch11-02.html index f4b5824..6c25c4f 100644 --- a/ch11/ch11-02.html +++ b/ch11/ch11-02.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch11/ch11-03.html b/ch11/ch11-03.html index 5c7e45d..1562180 100644 --- a/ch11/ch11-03.html +++ b/ch11/ch11-03.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch11/ch11-04.html b/ch11/ch11-04.html index 1a91813..00c52e3 100644 --- a/ch11/ch11-04.html +++ b/ch11/ch11-04.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch11/ch11-05.html b/ch11/ch11-05.html index 0ccc905..d182bbd 100644 --- a/ch11/ch11-05.html +++ b/ch11/ch11-05.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch11/ch11-06.html b/ch11/ch11-06.html index 5b17355..a20b373 100644 --- a/ch11/ch11-06.html +++ b/ch11/ch11-06.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch11/ch11.html b/ch11/ch11.html index 343a9f1..6b3f984 100644 --- a/ch11/ch11.html +++ b/ch11/ch11.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch12/ch12-01.html b/ch12/ch12-01.html index 6240ba7..7902663 100644 --- a/ch12/ch12-01.html +++ b/ch12/ch12-01.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch12/ch12-02.html b/ch12/ch12-02.html index 5c760fb..614b639 100644 --- a/ch12/ch12-02.html +++ b/ch12/ch12-02.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch12/ch12-03.html b/ch12/ch12-03.html index 26bbfd5..cd7aadd 100644 --- a/ch12/ch12-03.html +++ b/ch12/ch12-03.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch12/ch12-04.html b/ch12/ch12-04.html index 796b346..88ce86c 100644 --- a/ch12/ch12-04.html +++ b/ch12/ch12-04.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch12/ch12-05.html b/ch12/ch12-05.html index 76b0b66..8085560 100644 --- a/ch12/ch12-05.html +++ b/ch12/ch12-05.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 diff --git a/ch12/ch12-06.html b/ch12/ch12-06.html index 1b567a2..72c5c04 100644 --- a/ch12/ch12-06.html +++ b/ch12/ch12-06.html @@ -84,7 +84,7 @@ - Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 并发的退出8.9. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. 竞争条件检测9.6. 示例: 并发的非阻塞缓存9.7. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 显示一个类型的方法集12.8. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 + Go语言圣经前言1. 入门1.1. Hello, World1.2. 命令行参数1.3. 查找重复的行1.4. GIF动画1.5. 获取URL1.6. 并发获取多个URL1.7. Web服务1.8. 本章要点2. 程序结构2.1. 命名2.2. 声明2.3. 变量2.4. 赋值2.5. 类型2.6. 包和文件2.7. 作用域3. 基础数据类型3.1. 整型3.2. 浮点数3.3. 复数3.4. 布尔型3.5. 字符串3.6. 常量4. 复合数据类型4.1. 数组4.2. Slice4.3. Map4.4. 结构体4.5. JSON4.6. 文本和HTML模板5. 函数5.1. 函数声明5.2. 递归5.3. 多返回值5.4. 错误5.5. 函数值5.6. 匿名函数5.7. 可变参数5.8. Deferred函数5.9. Panic异常5.10. Recover捕获异常6. 方法6.1. 方法声明6.2. 基于指针对象的方法6.3. 通过嵌入结构体来扩展类型6.4. 方法值和方法表达式6.5. 示例: Bit数组6.6. 封装7. 接口7.1. 接口是合约7.2. 接口类型7.3. 实现接口的条件7.4. flag.Value接口7.5. 接口值7.6. sort.Interface接口7.7. http.Handler接口7.8. error接口7.9. 示例: 表达式求值7.10. 类型断言7.11. 基于类型断言识别错误类型7.12. 通过类型断言查询接口7.13. 类型分支7.14. 示例: 基于标记的XML解码7.15. 补充几点8. Goroutines和Channels8.1. Goroutines8.2. 示例: 并发的Clock服务8.3. 示例: 并发的Echo服务8.4. Channels8.5. 并发的循环8.6. 示例: 并发的Web爬虫8.7. 基于select的多路复用8.8. 示例: 并发的目录遍历8.9. 并发的退出8.10. 示例: 聊天服务9. 基于共享变量的并发9.1. 竞争条件9.2. sync.Mutex互斥锁9.3. sync.RWMutex读写锁9.4. 内存同步9.5. sync.Once惰性初始化9.6. 竞争条件检测9.7. 示例: 并发的非阻塞缓存9.8. Goroutines和线程10. 包和工具10.1. 包简介10.2. 导入路径10.3. 包声明10.4. 导入声明10.5. 包的匿名导入10.6. 包和命名10.7. 工具11. 测试11.1. go test11.2. 测试函数11.3. 测试覆盖率11.4. 基准测试11.5. 剖析11.6. 示例函数12. 反射12.1. 为何需要反射?12.2. reflect.Type和reflect.Value12.3. Display递归打印12.4. 示例: 编码S表达式12.5. 通过reflect.Value修改值12.6. 示例: 解码S表达式12.7. 获取结构体字段标签12.8. 显示一个类型的方法集12.9. 几点忠告13. 底层编程13.1. unsafe.Sizeof, Alignof 和 Offsetof13.2. unsafe.Pointer13.3. 示例: 深度相等判断13.4. 通过cgo调用C代码13.5. 几点忠告14. 附录14.1. 附录A:原文勘误14.2. 附录B:作者译者14.3. 附录C:译文授权14.4. 附录D:其它语言 @@ -322,7 +322,7 @@ func Unmarshal(data []byte, out interface{}) (err error) { - + @@ -336,7 +336,7 @@ func Unmarshal(data []byte, out interface{}) (err error) { - + diff --git a/ch12/ch12-07.html b/ch12/ch12-07.html new file mode 100644 index 0000000..8513e57 --- /dev/null +++ b/ch12/ch12-07.html @@ -0,0 +1,354 @@ + + +
在4.5节我们使用构体成员标签用于设置对应JSON对应的名字。其中json成员标签让我们可以选择成员的名字和抑制零值成员的输出。在本节,我们将看到如何通过反射机制类获取成员标签。
对于一个web服务,大部分HTTP处理函数要做的第一件事情就是展开请求中的参数到本地变量中。我们定义了一个工具函数,叫params.Unpack,通过使用结构体成员标签机制来让HTTP处理函数解析请求参数更方便。
首先,我们看看如何使用它。下面的search函数是一个HTTP请求处理函数。它定义了一个匿名结构体类型的变量,用结构体的每个成员表示HTTP请求的参数。其中结构体成员标签指明了对于请求参数的名字,为了减少URL的长度这些参数名通常都是神秘的缩略词。Unpack将请求参数填充到合适的结构体成员中,这样我们可以方便地通过合适的类型类来访问这些参数。
gopl.io/ch12/search
import "gopl.io/ch12/params" + +// search implements the /search URL endpoint. +func search(resp http.ResponseWriter, req *http.Request) { + var data struct { + Labels []string `http:"l"` + MaxResults int `http:"max"` + Exact bool `http:"x"` + } + data.MaxResults = 10 // set default + if err := params.Unpack(req, &data); err != nil { + http.Error(resp, err.Error(), http.StatusBadRequest) // 400 + return + } + + // ...rest of handler... + fmt.Fprintf(resp, "Search: %+v\n", data) +} +
下面的Unpack函数主要完成三件事情。第一,它调用req.ParseForm()来解析HTTP请求。然后,req.Form将包含所有的请求参数,不管HTTP客户端使用的是GET还是POST请求方法。
下一步,Unpack函数将构建每个结构体成员有效参数名字到成员变量的映射。如果结构体成员有成员标签的话,有效参数名字可能和实际的成员名字不相同。reflect.Type的Field方法将返回一个reflect.StructField,里面含有每个成员的名字、类型和可选的成员标签等信息。其中成员标签信息对应reflect.StructTag类型的字符串,并且提供了Get方法用于解析和根据特定key提取的子串,例如这里的http:"..."形式的子串。
gopl.io/ch12/params
// Unpack populates the fields of the struct pointed to by ptr +// from the HTTP request parameters in req. +func Unpack(req *http.Request, ptr interface{}) error { + if err := req.ParseForm(); err != nil { + return err + } + + // Build map of fields keyed by effective name. + fields := make(map[string]reflect.Value) + v := reflect.ValueOf(ptr).Elem() // the struct variable + for i := 0; i < v.NumField(); i++ { + fieldInfo := v.Type().Field(i) // a reflect.StructField + tag := fieldInfo.Tag // a reflect.StructTag + name := tag.Get("http") + if name == "" { + name = strings.ToLower(fieldInfo.Name) + } + fields[name] = v.Field(i) + } + + // Update struct field for each parameter in the request. + for name, values := range req.Form { + f := fields[name] + if !f.IsValid() { + continue // ignore unrecognized HTTP parameters + } + for _, value := range values { + if f.Kind() == reflect.Slice { + elem := reflect.New(f.Type().Elem()).Elem() + if err := populate(elem, value); err != nil { + return fmt.Errorf("%s: %v", name, err) + } + f.Set(reflect.Append(f, elem)) + } else { + if err := populate(f, value); err != nil { + return fmt.Errorf("%s: %v", name, err) + } + } + } + } + return nil +} +
最后,Unpack遍历HTTP请求的name/valu参数键值对,并且根据更新相应的结构体成员。回想一下,同一个名字的参数可能出现多次。如果发生这种情况,并且对应的结构体成员是一个slice,那么就将所有的参数添加到slice中。其它情况,对应的成员值将被覆盖,只有最后一次出现的参数值才是起作用的。
populate函数小心用请求的字符串类型参数值来填充单一的成员v(或者是slice类型成员中的单一的元素)。目前,它仅支持字符串、有符号整数和布尔型。其中其它的类型将留做练习任务。
func populate(v reflect.Value, value string) error { + switch v.Kind() { + case reflect.String: + v.SetString(value) + + case reflect.Int: + i, err := strconv.ParseInt(value, 10, 64) + if err != nil { + return err + } + v.SetInt(i) + + case reflect.Bool: + b, err := strconv.ParseBool(value) + if err != nil { + return err + } + v.SetBool(b) + + default: + return fmt.Errorf("unsupported kind %s", v.Type()) + } + return nil +} +
如果我们上上面的处理程序添加到一个web服务器,则可以产生以下的会话:
$ go build gopl.io/ch12/search +$ ./search & +$ ./fetch 'http://localhost:12345/search' +Search: {Labels:[] MaxResults:10 Exact:false} +$ ./fetch 'http://localhost:12345/search?l=golang&l=programming' +Search: {Labels:[golang programming] MaxResults:10 Exact:false} +$ ./fetch 'http://localhost:12345/search?l=golang&l=programming&max=100' +Search: {Labels:[golang programming] MaxResults:100 Exact:false} +$ ./fetch 'http://localhost:12345/search?x=true&l=golang&l=programming' +Search: {Labels:[golang programming] MaxResults:10 Exact:true} +$ ./fetch 'http://localhost:12345/search?q=hello&x=123' +x: strconv.ParseBool: parsing "123": invalid syntax +$ ./fetch 'http://localhost:12345/search?q=hello&max=lots' +max: strconv.ParseInt: parsing "lots": invalid syntax +
练习 12.11: 编写相应的Pack函数,给定一个结构体值,Pack函数将返回合并了所有结构体成员和值的URL。
练习 12.12: 扩展成员标签以表示一个请求参数的有效值规则。例如,一个字符串可以是有效的email地址或一个信用卡号码,还有一个整数可能需要是有效的邮政编码。修改Unpack函数以检查这些规则。
练习 12.13: 修改S表达式的编码器(§12.4)和解码器(§12.6),采用和encoding/json包(§4.5)类似的方式使用成员标签中的sexpr:"..."字串。
在本小节中,我们会创建一个程序来生成指定目录的硬盘使用情况报告,这个程序和Unix里的du工具比较相似。大多数工作用下面这个walkDir函数来完成,这个函数使用dirents函数来枚举一个目录下的所有入口。
gopl.io/ch8/du1
// walkDir recursively walks the file tree rooted at dir +// and sends the size of each found file on fileSizes. +func walkDir(dir string, fileSizes chan<- int64) { + for _, entry := range dirents(dir) { + if entry.IsDir() { + subdir := filepath.Join(dir, entry.Name()) + walkDir(subdir, fileSizes) + } else { + fileSizes <- entry.Size() + } + } +} + +// dirents returns the entries of directory dir. +func dirents(dir string) []os.FileInfo { + entries, err := ioutil.ReadDir(dir) + if err != nil { + fmt.Fprintf(os.Stderr, "du1: %v\n", err) + return nil + } + return entries +} +
ioutil.ReadDir函数会返回一个os.FileInfo类型的slice,os.FileInfo类型也是os.Stat这个函数的返回值。对每一个子目录而言,walkDir会递归地调用其自身,同时也在递归里获取每一个文件的信息。walkDir函数会向fileSizes这个channel发送一条消息。这条消息包含了文件的字节大小。
下面的主函数,用了两个goroutine。后台的goroutine调用walkDir来遍历命令行给出的每一个路径并最终关闭fileSizes这个channel。主goroutine会对其从channel中接收到的文件大小进行累加,并输出其和。
package main + +import ( + "flag" + "fmt" + "io/ioutil" + "os" + "path/filepath" +) + +func main() { + // Determine the initial directories. + flag.Parse() + roots := flag.Args() + if len(roots) == 0 { + roots = []string{"."} + } + + // Traverse the file tree. + fileSizes := make(chan int64) + go func() { + for _, root := range roots { + walkDir(root, fileSizes) + } + close(fileSizes) + }() + + // Print the results. + var nfiles, nbytes int64 + for size := range fileSizes { + nfiles++ + nbytes += size + } + printDiskUsage(nfiles, nbytes) +} + +func printDiskUsage(nfiles, nbytes int64) { + fmt.Printf("%d files %.1f GB\n", nfiles, float64(nbytes)/1e9) +} +
这个程序会在打印其结果之前卡住很长时间。
$ go build gopl.io/ch8/du1 +$ ./du1 $HOME /usr /bin /etc +213201 files 62.7 GB +
如果在运行的时候能够让我们知道处理进度的话想必更好。但是,如果简单地把printDiskUsage函数调用移动到循环里会导致其打印出成百上千的输出。
下面这个du的变种会间歇打印内容,不过只有在调用时提供了-v的flag才会显示程序进度信息。在roots目录上循环的后台goroutine在这里保持不变。主goroutine现在使用了计时器来每500ms生成事件,然后用select语句来等待文件大小的消息来更新总大小数据,或者一个计时器的事件来打印当前的总大小数据。如果-v的flag在运行时没有传入的话,tick这个channel会保持为nil,这样在select里的case也就相当于被禁用了。
gopl.io/ch8/du2
var verbose = flag.Bool("v", false, "show verbose progress messages") + +func main() { + // ...start background goroutine... + + // Print the results periodically. + var tick <-chan time.Time + if *verbose { + tick = time.Tick(500 * time.Millisecond) + } + var nfiles, nbytes int64 +loop: + for { + select { + case size, ok := <-fileSizes: + if !ok { + break loop // fileSizes was closed + } + nfiles++ + nbytes += size + case <-tick: + printDiskUsage(nfiles, nbytes) + } + } + printDiskUsage(nfiles, nbytes) // final totals +} +
由于我们的程序不再使用range循环,第一个select的case必须显式地判断fileSizes的channel是不是已经被关闭了,这里可以用到channel接收的二值形式。如果channel已经被关闭了的话,程序会直接退出循环。这里的break语句用到了标签break,这样可以同时终结select和for两个循环;如果没有用标签就break的话只会退出内层的select循环,而外层的for循环会使之进入下一轮select循环。
现在程序会悠闲地为我们打印更新流:
$ go build gopl.io/ch8/du2 +$ ./du2 -v $HOME /usr /bin /etc +28608 files 8.3 GB +54147 files 10.3 GB +93591 files 15.1 GB +127169 files 52.9 GB +175931 files 62.2 GB +213201 files 62.7 GB +
然而这个程序还是会花上很长时间才会结束。完全可以并发调用walkDir,从而发挥磁盘系统的并行性能。下面这个第三个版本的du,会对每一个walkDir的调用创建一个新的goroutine。它使用sync.WaitGroup(§8.5)来对仍旧活跃的walkDir调用进行计数,另一个goroutine会在计数器减为零的时候将fileSizes这个channel关闭。
gopl.io/ch8/du3
func main() { + // ...determine roots... + // Traverse each root of the file tree in parallel. + fileSizes := make(chan int64) + var n sync.WaitGroup + for _, root := range roots { + n.Add(1) + go walkDir(root, &n, fileSizes) + } + go func() { + n.Wait() + close(fileSizes) + }() + // ...select loop... +} + +func walkDir(dir string, n *sync.WaitGroup, fileSizes chan<- int64) { + defer n.Done() + for _, entry := range dirents(dir) { + if entry.IsDir() { + n.Add(1) + subdir := filepath.Join(dir, entry.Name()) + go walkDir(subdir, n, fileSizes) + } else { + fileSizes <- entry.Size() + } + } +} +
由于这个程序在高峰期会创建成百上千的goroutine,我们需要修改dirents函数,用计数信号量来阻止他同时打开太多的文件,就像我们在8.7节中的并发爬虫一样:
// sema is a counting semaphore for limiting concurrency in dirents. +var sema = make(chan struct{}, 20) + +// dirents returns the entries of directory dir. +func dirents(dir string) []os.FileInfo { + sema <- struct{}{} // acquire token + defer func() { <-sema }() // release token + // ... +
这个版本比之前那个快了好几倍,尽管其具体效率还是和你的运行环境,机器配置相关。
练习 8.9: 编写一个du工具,每隔一段时间将root目录下的目录大小计算并显示出来。
如果初始化成本比较大的话,那么将初始化延迟到需要的时候再去做就是一个比较好的选择。如果在程序启动的时候就去做这类初始化的话,会增加程序的启动时间,并且因为执行的时候可能也并不需要这些变量,所以实际上有一些浪费。让我们来看在本章早一些时候的icons变量:
var icons map[string]image.Image +
这个版本的Icon用到了懒初始化(lazy initialization)。
func loadIcons() { + icons = map[string]image.Image{ + "spades.png": loadIcon("spades.png"), + "hearts.png": loadIcon("hearts.png"), + "diamonds.png": loadIcon("diamonds.png"), + "clubs.png": loadIcon("clubs.png"), + } +} + +// NOTE: not concurrency-safe! +func Icon(name string) image.Image { + if icons == nil { + loadIcons() // one-time initialization + } + return icons[name] +} +
如果一个变量只被一个单独的goroutine所访问的话,我们可以使用上面的这种模板,但这种模板在Icon被并发调用时并不安全。就像前面银行的那个Deposit(存款)函数一样,Icon函数也是由多个步骤组成的:首先测试icons是否为空,然后load这些icons,之后将icons更新为一个非空的值。直觉会告诉我们最差的情况是loadIcons函数被多次访问会带来数据竞争。当第一个goroutine在忙着loading这些icons的时候,另一个goroutine进入了Icon函数,发现变量是nil,然后也会调用loadIcons函数。
不过这种直觉是错误的。(我们希望你从现在开始能够构建自己对并发的直觉,也就是说对并发的直觉总是不能被信任的!),回忆一下9.4节。因为缺少显式的同步,编译器和CPU是可以随意地去更改访问内存的指令顺序,以任意方式,只要保证每一个goroutine自己的执行顺序一致。其中一种可能loadIcons的语句重排是下面这样。它会在填写icons变量的值之前先用一个空map来初始化icons变量。
func loadIcons() { + icons = make(map[string]image.Image) + icons["spades.png"] = loadIcon("spades.png") + icons["hearts.png"] = loadIcon("hearts.png") + icons["diamonds.png"] = loadIcon("diamonds.png") + icons["clubs.png"] = loadIcon("clubs.png") +} +
因此,一个goroutine在检查icons是非空时,也并不能就假设这个变量的初始化流程已经走完了(译注:可能只是塞了个空map,里面的值还没填完,也就是说填值的语句都没执行完呢)。
最简单且正确的保证所有goroutine能够观察到loadIcons效果的方式,是用一个mutex来同步检查。
var mu sync.Mutex // guards icons +var icons map[string]image.Image + +// Concurrency-safe. +func Icon(name string) image.Image { + mu.Lock() + defer mu.Unlock() + if icons == nil { + loadIcons() + } + return icons[name] +} +
然而使用互斥访问icons的代价就是没有办法对该变量进行并发访问,即使变量已经被初始化完毕且再也不会进行变动。这里我们可以引入一个允许多读的锁:
var mu sync.RWMutex // guards icons +var icons map[string]image.Image +// Concurrency-safe. +func Icon(name string) image.Image { + mu.RLock() + if icons != nil { + icon := icons[name] + mu.RUnlock() + return icon + } + mu.RUnlock() + + // acquire an exclusive lock + mu.Lock() + if icons == nil { // NOTE: must recheck for nil + loadIcons() + } + icon := icons[name] + mu.Unlock() + return icon +} +
上面的代码有两个临界区。goroutine首先会获取一个读锁,查询map,然后释放锁。如果条目被找到了(一般情况下),那么会直接返回。如果没有找到,那goroutine会获取一个写锁。不释放共享锁的话,也没有任何办法来将一个共享锁升级为一个互斥锁,所以我们必须重新检查icons变量是否为nil,以防止在执行这一段代码的时候,icons变量已经被其它gorouine初始化过了。
上面的模板使我们的程序能够更好的并发,但是有一点太复杂且容易出错。幸运的是,sync包为我们提供了一个专门的方案来解决这种一次性初始化的问题:sync.Once。概念上来讲,一次性的初始化需要一个互斥量mutex和一个boolean变量来记录初始化是不是已经完成了;互斥量用来保护boolean变量和客户端数据结构。Do这个唯一的方法需要接收初始化函数作为其参数。让我们用sync.Once来简化前面的Icon函数吧:
var loadIconsOnce sync.Once +var icons map[string]image.Image +// Concurrency-safe. +func Icon(name string) image.Image { + loadIconsOnce.Do(loadIcons) + return icons[name] +} +
每一次对Do(loadIcons)的调用都会锁定mutex,并会检查boolean变量(译注:Go1.9中会先判断boolean变量是否为1(true),只有不为1才锁定mutex,不再需要每次都锁定mutex)。在第一次调用时,boolean变量的值是false,Do会调用loadIcons并会将boolean变量设置为true。随后的调用什么都不会做,但是mutex同步会保证loadIcons对内存(这里其实就是指icons变量啦)产生的效果能够对所有goroutine可见。用这种方式来使用sync.Once的话,我们能够避免在变量被构建完成之前和其它goroutine共享该变量。
练习 9.2: 重写2.6.2节中的PopCount的例子,使用sync.Once,只在第一次需要用到的时候进行初始化。(虽然实际上,对PopCount这样很小且高度优化的函数进行同步可能代价没法接受。)
channel的零值是nil。也许会让你觉得比较奇怪,nil的channel有时候也是有一些用处的。因为对一个nil的channel发送和接收操作会永远阻塞,在select语句中操作nil的channel永远都不会被select到。
这使得我们可以用nil来激活或者禁用case,来达成处理其它输入或输出事件时超时和取消的逻辑。我们会在下一节中看到一个例子。
练习 8.8: 使用select来改造8.3节中的echo服务器,为其增加超时,这样服务器可以在客户端10秒中没有任何喊话时自动断开连接。
有时候我们需要通知goroutine停止它正在干的事情,比如一个正在执行计算的web服务,然而它的客户端已经断开了和服务端的连接。
Go语言并没有提供在一个goroutine中终止另一个goroutine的方法,由于这样会导致goroutine之间的共享变量落在未定义的状态上。在8.7节中的rocket launch程序中,我们往名字叫abort的channel里发送了一个简单的值,在countdown的goroutine中会把这个值理解为自己的退出信号。但是如果我们想要退出两个或者任意多个goroutine怎么办呢?
在一个独立的goroutine中,每一个语句的执行顺序是可以被保证的,也就是说goroutine内顺序是连贯的。但是在不使用channel且不使用mutex这样的显式同步操作时,我们就没法保证事件在不同的goroutine中看到的执行顺序是一致的了。尽管goroutine A中一定需要观察到x=1执行成功之后才会去读取y,但它没法确保自己观察得到goroutine B中对y的写入,所以A还可能会打印出y的一个旧版的值。
尽管去理解并发的一种尝试是去将其运行理解为不同goroutine语句的交错执行,但看看上面的例子,这已经不是现代的编译器和cpu的工作方式了。因为赋值和打印指向不同的变量,编译器可能会断定两条语句的顺序不会影响执行结果,并且会交换两个语句的执行顺序。如果两个goroutine在不同的CPU上执行,每一个核心有自己的缓存,这样一个goroutine的写入对于其它goroutine的Print,在主存同步之前就是不可见的了。
所有并发的问题都可以用一致的、简单的既定的模式来规避。所以可能的话,将变量限定在goroutine内部;如果是多个goroutine都需要访问的变量,使用互斥条件来访问。
即使我们小心到不能再小心,但在并发程序中犯错还是太容易了。幸运的是,Go的runtime和工具链为我们装备了一个复杂但好用的动态分析工具,竞争检查器(the race detector)。
只要在go build,go run或者go test命令后面加上-race的flag,就会使编译器创建一个你的应用的“修改”版或者一个附带了能够记录所有运行期对共享变量访问工具的test,并且会记录下每一个读或者写共享变量的goroutine的身份信息。另外,修改版的程序会记录下所有的同步事件,比如go语句,channel操作,以及对(*sync.Mutex).Lock,(*sync.WaitGroup).Wait等等的调用。(完整的同步事件集合是在The Go Memory Model文档中有说明,该文档是和语言文档放在一起的。译注:https://golang.org/ref/mem )
(*sync.Mutex).Lock
(*sync.WaitGroup).Wait
练习 12.8: sexpr.Unmarshal函数和json.Unmarshal一样,都要求在解码前输入完整的字节slice。定义一个和json.Decoder类似的sexpr.Decoder类型,支持从一个io.Reader流解码。修改sexpr.Unmarshal函数,使用这个新的类型实现。
练习 12.9: 编写一个基于标记的API用于解码S表达式,参考xml.Decoder(7.14)的风格。你将需要五种类型的标记:Symbol、String、Int、StartList和EndList。
练习 12.10: 扩展sexpr.Unmarshal函数,支持布尔型、浮点数和interface类型的解码,使用 练习 12.3: 的方案。(提示:要解码接口,你需要将name映射到每个支持类型的reflect.Type。)
我们的最后一个例子是使用reflect.Type来打印任意值的类型和枚举它的方法:
gopl.io/ch12/methods
A: {{.A}}
B: {{.B}}