(1)本书内容丰富,技术含量高,深浅出,竞争力强。本书的目标是让先教读者学会编写Go程序,然后帮助他们掌握Go语言的精髓,最后了解Go语言背后的设计,从而提高发者解决复杂底层问题的能力。 (2)本书结构清晰全面。本书以普通应用发者会涉及的知识为纲要,深剖析了这些知识的底层机制,全面而透彻。 (3)内容由浅深,便于理解。顺序阅读,会起到很好效果。当然,也可用于查询式阅读。
售 价:¥
纸质售价:¥104.30购买纸书
温馨提示:数字商品不支持退换货,不提供源文件,不支持导出打印
为你推荐
版 权
内 容 提 要
前 言
资源与支持
第1章 Go语言初探
1.1 Go语言的发展里程碑
1.2 云时代Go语言的发展趋势
1.3 Go语言优秀的语言特性
1.3.1 “少即是多”的设计哲学
1.3.2 强大的runtime
1.3.3 面向接口编程
1.3.4 为工程服务的语言
1.3.5 自带标准化的测试框架
1.3.6 丰富的标准库和第三方库
1.4 强大的生态圈和成功案例
1.5 Go程序是如何运行的
1.6 plan9与Go语言
1.6.1 寄存器
1.6.2 Go语言的反汇编方法
1.6.3 反汇编的查看示例
第2章 “hello world”与工具链
2.1 Go语言的安装和配置
2.1.1 下载和安装
2.1.2 配置Go语言的环境变量
2.1.3 查看配置信息
2.2 第一个程序“hello world”
2.2.1 “hello world”程序的代码说明
2.2.2 代码的编译与运行
2.2.3 “hello world”示例总结
2.3 Go语言的工具链命令
2.3.1 与编译执行有关的工具链命令
2.3.2 获取与安装第三方包
2.3.3 工具包组合命令go tool
2.3.4 跨平台交叉编译
2.3.5 网络代理GOPROXY
第3章 Go语言的基础知识
3.1 Go语言的常用规范
3.1.1 命名与注释
3.1.2 声明
3.1.3 对变量赋值
3.1.4 包和文件
3.2 数据类型
3.2.1 基本类型
3.2.2 非引用类型和引用类型
3.2.3 用户自定义类型
3.2.4 类型别名
3.2.5 传参方式
3.3 变量的本质
3.3.1 类型的两个要素
3.3.2 变量的声明
3.3.3 零值机制
3.3.4 短变量声明与类型转换
3.4 常量
3.4.1 常量iota
3.4.2 常量的类型提升机制
3.5 运算符
3.5.1 算术运算符
3.5.2 比较运算符
3.5.3 逻辑运算符
3.5.4 位运算符
3.5.5 赋值运算符
3.5.6 指针运算符
3.6 结构化语法
3.6.1 循环结构
3.6.2 条件语句
3.6.3 switch-case语句
3.6.4 控制或跳出循环语句的关键字
3.7 类型转换
3.7.1 转换的语法
3.7.2 类型断言
3.8 Go语言的语法糖
3.8.1 短变量声明和new函数
3.8.2 符号“...”与切片
3.8.3 for range
第4章 面向包的设计与依赖管理
4.1 包的使用
4.1.1 包的概述
4.1.2 包的查找方式
4.1.3 包加载的顺序
4.1.4 包中init函数的加载
4.1.5 包加载顺序的示例
4.1.6 包的使用总结
4.2 面向包的设计
4.3 包管理工具Go Module
4.3.1 包管理的方式
4.3.2 Go Module简介
4.3.3 开启Go Module
4.3.4 Go Module的优点
4.3.5 使用Go Module
4.3.6 go.mod文件中的命令
4.3.7 升级依赖包的方法
4.3.8 依赖包版本的选择
4.3.9 语义版本的导入路径语法
4.3.10 Go Module的使用总结
第5章 测试框架
5.1 Go语言中的测试框架
5.1.1 测试使用的约定
5.1.2 标准库testing的辅助功能函数
5.1.3 测试框架示例
5.1.4 使用测试命令
5.2 单元测试
5.2.1 指定测试用例
5.2.2 单元测试之子测试
5.2.3 帮助函数
5.3 测试代码的覆盖率
5.4 断言
5.5 基准测试
5.5.1 基准测试场景
5.5.2 基准测试的方法
5.5.3 基准测试之子测试
5.5.4 基准测试示例
5.6 与网络有关的模拟测试
5.7 与测试有关的第三方工具
5.7.1 gomock
5.7.2 BDD
第6章 错误与异常处理
6.1 error的引入
6.1.1 预定义的错误类型
6.1.2 快速创建错误类型
6.1.3 自定义错误
6.1.4 接口在错误处理上的妙用
6.1.5 自定义错误的陷阱
6.1.6 获取和处理错误
6.1.7 Go语言作者关于错误处理的观点
6.2 异常处理
6.2.1 panic的使用
6.2.2 defer函数的设计与使用陷阱
6.2.3 recover函数的使用
6.3 面向错误和恢复的设计
6.4 带堆栈信息的error
6.5 标准库errors的改进
6.6 errGroup对象
6.7 日志系统的引入
6.7.1 日志概述
6.7.2 第三方日志框架
第7章 编码与字符串
7.1 字符编码
7.1.1 字符的编码方式
7.1.2 使用字符类型的注意事项
7.2 字符串
7.2.1 字符串的声明和初始化
7.2.2 字符串的数据结构
7.2.3 遍历字符串
7.2.4 字符串的长度问题
7.2.5 字符串的备份
7.2.6 字符串拼接
7.3 字符串与基本类型互转
第8章 指针与内存逃逸分析
8.1 活动帧的作用
8.2 值语义的本质
8.3 指针
8.3.1 指针的由来
8.3.2 指针和指针类型
8.3.3 使用指针运算符的注意事项
8.3.4 nil指针
8.3.5 指针数组与数组指针
8.3.6 关于指针的补充说明
8.4 内存逃逸分析
8.4.1 内存逃逸分析的由来
8.4.2 内存逃逸分析的作用
8.4.3 两种情况会引起内存逃逸分析
8.4.4 内存逃逸分析示例
8.4.5 函数内联
8.4.6 手动控制内存逃逸分析
8.5 引用类型与深、浅拷贝
第9章 数据结构
9.1 面向数据的设计
9.1.1 编码和硬件
9.1.2 可预测的内存访问模式
9.2 数组
9.2.1 数组的声明及初始化
9.2.2 数组在内存中的形式
9.2.3 遍历数组
9.2.4 数组的截取
9.2.5 数组的反转
9.3 切片
9.3.1 切片的设计
9.3.2 切片的创建与初始化
9.3.3 切片的长度与容量
9.3.4 nil切片和空切片
9.3.5 切片的共享底层数组
9.3.6 append函数与切片的扩容
9.3.7 append函数引发的内存泄漏
9.3.8 三下标切片
9.3.9 切片的复制
9.3.10 切片的比较
9.3.11 删除切片中的元素
9.3.12 特殊的切片:字符串
9.3.13 数组与切片的对比
9.4 映射
9.4.1 选择合适的键值类型
9.4.2 映射的声明和初始化
9.4.3 映射的使用
9.4.4 映射的排序
9.4.5 映射的扩容
9.4.6 映射的并发安全性
9.4.7 映射的删除机制
9.4.8 映射的设计
9.5 数据结构中的常见问题
9.5.1 make与new的差异
9.5.2 使用引用类型前先分配空间
9.5.3 可能发生内存泄漏的情况
第10章 结构体与内存对齐
10.1 结构体
10.1.1 结构体的定义
10.1.2 结构体的初始化
10.1.3 结构体的类型转换
10.1.4 结构体比较
10.1.5 结构体的值
10.2 序列化与反序列化
10.2.1 序列化
10.2.2 反序列化
10.2.3 使用tag
10.3 unsafe包
10.3.1 unsafe.Pointer类型
10.3.2 unsafe包简介
10.3.3 unsafe包中的函数
10.3.4 unsafe包的使用方式
10.4 内存对齐
10.4.1 内存对齐的概念
10.4.2 数据类型的尺寸
10.4.3 内存自动对齐
10.4.4 内存对齐的示例
第11章 函数
11.1 认识函数
11.1.1 函数的定义
11.1.2 函数的种类
11.2 defer函数
11.2.1 defer函数的使用场景
11.2.2 当panic遇到defer函数
11.2.3 defer函数与for循环语句
11.3 作为数据类型的函数
11.4 函数类型的使用场景
11.4.1 匿名函数
11.4.2 回调函数
11.4.3 闭包
11.5 函数的别名
第12章 面向“对象”编程
12.1 封装
12.1.1 方法
12.1.2 方法的声明方式
12.1.3 接收者类型与接收者基础类型
12.1.4 接收者使用的语义
12.1.5 两种语义本质上的区别
12.1.6 解耦带来的问题
12.1.7 更为复杂的调用方式
12.1.8 隐式转换
12.1.9 关于封装的总结
12.2 继承
12.2.1 Go语言不支持继承
12.2.2 用“内嵌+组合”替代继承
12.2.3 扩展已有的包
12.3 多态
12.3.1 接口的定义
12.3.2 鸭子类型
12.3.3 接口与协议
12.3.4 接口如何实现多态
第13章 面向接口编程
13.1 接口编程哲学
13.2 接口与组合
13.2.1 接口的设计准则
13.2.2 接口与组合示例
13.2.3 组合的多样化
13.3 接口的剖析
13.3.1 与接口相关的说明
13.3.2 空接口与包裹
13.3.3 实现接口类型
13.3.4 接口包裹非接口值
13.3.5 接口与多态
13.3.6 接口类型断言
13.3.7 强制转换接口类型
13.3.8 接口类型与隐式声明
13.3.9 类型转换的时间复杂度
13.4 接口的设计原则
13.4.1 错误的接口设计
13.4.2 基于数据驱动的接口设计
13.4.3 类型断言在API设计中的应用
13.4.4 接口设计的建议
13.5 检查接口的实现
13.6 空接口与类型断言
13.7 接口值的比较
13.8 检查运行阶段的接口类型
第14章 反射
14.1 反射的概念
14.2 接口与反射
14.2.1 静态类型与动态类型
14.2.2 空接口
14.2.3 类型的底层分析
14.3 反射包介绍
14.3.1 理解反射对象的转换机制
14.3.2 reflect.Type接口的转换方式
14.3.3 reflect.Value结构体类型的使用方法
14.4 反射包的使用示例
14.4.1 获取变量的类型和值
14.4.2 获取结构体的属性和方法
14.4.3 动态调用方法和传值
14.4.4 修改接口值
14.4.5 判断结构体实现了哪个接口
14.5 反射的三个定律
14.6 反射的应用场景
14.7 反射的性能
第15章 并发编程
15.1 感受并发的魅力
15.1.1 并发和并行
15.1.2 并发带来的好处
15.1.3 “hello goroutine”
15.1.4 协程的执行顺序
15.1.5 控制协程的几种方式
15.2 sync.WaitGroup
15.2.1 sync.WaitGroup的三个方法
15.2.2 使用sync.WaitGroup的模板
15.2.3 使用sync.WaitGroup时的注意事项
15.2.4 为sync.WaitGroup增加额外的功能
15.3 数据竞争问题
15.3.1 临界区
15.3.2 数据竞争的检测方法
15.3.3 解决临界区的数据安全问题
15.4 传统的锁
15.4.1 锁的概念
15.4.2 互斥锁Mutex
15.4.3 Mutex的工作模式
15.4.4 读写锁RWMutex
15.4.5 重入与TryLock
15.5 原子操作介绍
15.5.1 Go语言中的原子操作
15.5.2 atomic包的使用
第16章 并发与通道
16.1 通道的行为
16.2 创建通道
16.3 通道的特性
16.3.1 通道的成对性
16.3.2 通道的阻塞性
16.3.3 通道与死锁
16.3.4 让出当前协程的执行权
16.3.5 关闭通道
16.3.6 遍历通道
16.4 通道的其他特性
16.4.1 带缓冲的通道
16.4.2 缓冲区与延迟保障
16.4.3 通道的方向
16.4.4 通道的状态
16.5 通道的使用建议
16.6 select机制
16.6.1 select机制的介绍与示例
16.6.2 select与超时控制
16.7 通道的模式
16.7.1 等待任务模式
16.7.2 等待结果模式
16.7.3 等待完成模式
16.7.4 Pooling模式
16.7.5 流水线模式
16.7.6 FanOut/FanIn模式
16.7.7 Drop模式
第17章 其他并发技术
17.1 context包
17.1.1 context包的使用场景
17.1.2 context包中的接口和函数
17.1.3 context包的使用流程
17.1.4 context.Context接口
17.1.5 生成Context的方法
17.1.6 Context与请求超时
17.1.7 Context的使用总结
17.2 sync.Cond
17.3 sync.Once
17.4 sync.Map
17.5 sync.Pool
17.5.1 sync.Pool的介绍
17.5.2 缓存对象的生命周期
17.5.3 sync.Pool的使用场景及存在的问题
17.6 实现对象池
17.7 常用连接池
17.8 并发技术选型
第18章 并发原理
18.1 怎样让程序跑得更快
18.1.1 从单进程到多线程
18.1.2 工作任务的种类
18.2 Go语言中的协程
18.2.1 内核态线程与用户态线程
18.2.2 轻量级的协程
18.2.3 改造后的Go语言协程
18.2.4 简说Go语言协程的调度
18.2.5 协作式与抢占式调度器
18.2.6 协程与I/O多路复用
18.3 GPM调度流程
18.3.1 GPM调度模型
18.3.2 G的调度
18.3.3 P的调度
18.3.4 M的调度
18.3.5 探索调度器的调度流程
18.3.6 循环调度
18.3.7 任务执行函数execute
18.4 监控线程sysmon
18.5 main函数与协程的执行顺序
18.6 可视化分析GPM调度
18.6.1 使用trace分析GPM调度
18.6.2 使用GODEBUG调试GPM调度
18.7 深入探索通道
18.7.1 通道的底层数据结构hchan
18.7.2 发生阻塞的条件
18.7.3 select多路复用的底层逻辑
第19章 内存管理
19.1 runtime
19.2 内存分配模型
19.2.1 内存模型
19.2.2 内存分配过程
19.2.3 span与预设的内存大小和规格
19.3 内存管理单元
19.3.1 mspan
19.3.2 mheap
19.3.3 heapArena
19.3.4 mcentral
19.3.5 mcache
19.3.6 内存的多级分配管理
19.4 对象分类及分配策略
19.4.1 微小对象
19.4.2 小对象和大对象
19.5 堆内存分配总结
第20章 垃圾回收
20.1 垃圾回收算法
20.2 Go语言的垃圾回收算法
20.2.1 标记清扫算法
20.2.2 三色标记法
20.2.3 三色标记与并发问题
20.2.4 三色不变式与屏障技术
20.2.5 插入写屏障
20.2.6 删除写屏障
20.2.7 混合写屏障
20.2.8 并发增量式垃圾回收
20.3 触发垃圾回收的时机
20.4 查看运行时的垃圾回收信息
20.5 垃圾回收优化示例
20.5.1 传递复杂对象时建议使用指针
20.5.2 自动扩容的代价
第21章 使用标准库和第三方库
21.1 I/O操作
21.1.1 io包
21.1.2 os包
21.1.3 bufio包
21.1.4 bytes包
21.1.5 ioutil包与替换方案
21.1.6 读取文件的示例
21.1.7 大文件读取方案
21.1.8 文件的复制
21.1.9 断点续传
21.2 网络操作
21.2.1 Socket编程
21.2.2 net/http包
21.2.3 与网络编程相关的其他包
21.3 与时间有关的标准库
21.3.1 时间函数
21.3.2 时间戳
21.3.3 时间的格式化与解析
21.4 随机数
21.5 正则表达式
21.6 flag包的使用
21.6.1 简单标记的声明方式
21.6.2 其他使用方式
21.7 os包的使用
21.8 crypto包
21.9 base64编码
21.10 fmt包
21.11 使用第三方库
第22章 性能问题分析与追踪
22.1 性能优化概述
22.2 性能优化的步骤
22.3 硬件与软件的性能指标
22.4 优化工具概述
22.4.1 runtime.MemStats
22.4.2 Benchmark
22.4.3 go tool pprof工具
22.4.4 runtime/pprof包
22.4.5 net/http/pprof包
22.4.6 go tool trace工具
22.4.7 fgprof包
22.4.8 coredump
22.4.9 gcflags
22.4.10 GODEBUG
22.4.11 使用场景总结
22.5 性能优化总结
22.6 使用go tool pprof工具进行性能分析的示例
22.7 pprof包结合HTTP服务使用的示例
22.8 pprof包和fgprof包的使用对比
22.9 go tool trace工具的使用示例
22.10 持续性能分析
22.11 性能问题的定位及处理建议
22.11.1 CPU占用率高的定位及处理建议
22.11.2 内存使用率高的定位及处理建议
22.11.3 I/O高的定位及处理建议
22.11.4 阻塞问题的定位及处理建议
22.11.5 协程泄露的定位及处理建议
第23章 重构“hello world”
23.1 搭建业务处理框架
23.2 设计解耦的读写接口
23.2.1 用结构体代替读写方法
23.2.2 使用组合接口
23.3 业务实现
23.3.1 读日志数据
23.3.2 Nginx日志数据的说明及处理
23.3.3 处理日志数据的关键代码
23.3.4 实现数据归档
23.4 构建HTTP服务发布数据
23.4.1 埋点处理
23.4.2 构建HTTP服务发布数据的步骤
23.5 整合Prometheus发布数据
23.5.1 引用第三方prometheus包
23.5.2 实现自定义的exporter
23.6 代码细节的提升
23.7 总结
买过这本书的人还买过
读了这本书的人还在读
同类图书排行榜