mirror of
https://github.com/chai2010/advanced-go-programming-book.git
synced 2025-05-24 12:32:21 +00:00
规范目录编号
This commit is contained in:
parent
fffa93b0cd
commit
196df74992
128
SUMMARY.md
128
SUMMARY.md
@ -1,69 +1,69 @@
|
||||
# 目录
|
||||
|
||||
* [第一章 语言基础](ch1-basic/readme.md)
|
||||
* [1.1. Go语言创世纪](ch1-basic/ch1-01-genesis.md)
|
||||
* [1.2. Hello, World 的革命](ch1-basic/ch1-02-hello-revolution.md)
|
||||
* [1.3. 数组、字符串和切片](ch1-basic/ch1-03-array-string-and-slice.md)
|
||||
* [1.4. 函数、方法和接口](ch1-basic/ch1-04-func-method-interface.md)
|
||||
* [1.5. 面向并发的内存模型](ch1-basic/ch1-05-mem.md)
|
||||
* [1.6. 常见的并发模式](ch1-basic/ch1-06-goroutine.md)
|
||||
* [1.7. 错误和异常](ch1-basic/ch1-07-error-and-panic.md)
|
||||
* [1.8. 补充说明](ch1-basic/ch1-08-ext.md)
|
||||
* [第二章 CGO编程](ch2-cgo/readme.md)
|
||||
* [2.1. 快速入门](ch2-cgo/ch2-01-hello-cgo.md)
|
||||
* [2.2. CGO基础](ch2-cgo/ch2-02-basic.md)
|
||||
* [2.3. 类型转换](ch2-cgo/ch2-03-cgo-types.md)
|
||||
* [2.4. 函数调用](ch2-cgo/ch2-04-func.md)
|
||||
* [2.5. 内部机制](ch2-cgo/ch2-05-internal.md)
|
||||
* [2.6. 实战: 封装qsort](ch2-cgo/ch2-06-qsort.md)
|
||||
* [2.7. CGO内存模型](ch2-cgo/ch2-07-memory.md)
|
||||
* [2.8. C++类包装](ch2-cgo/ch2-08-class.md)
|
||||
* [2.9. 静态库和动态库](ch2-cgo/ch2-09-static-shared-lib.md)
|
||||
* [2.10. 编译和链接参数](ch2-cgo/ch2-10-link.md)
|
||||
* [2.11. 补充说明](ch2-cgo/ch2-11-ext.md)
|
||||
* [第三章 汇编语言](ch3-asm/readme.md)
|
||||
* [3.1. 快速入门](ch3-asm/ch3-01-basic.md)
|
||||
* [3.2. 计算机结构](ch3-asm/ch3-02-arch.md)
|
||||
* [3.3. 常量和全局变量](ch3-asm/ch3-03-const-and-var.md)
|
||||
* [3.4. 函数](ch3-asm/ch3-04-func.md)
|
||||
* [3.5. 控制流](ch3-asm/ch3-05-control-flow.md)
|
||||
* [3.6. 再论函数](ch3-asm/ch3-06-func-again.md)
|
||||
* [3.7. 汇编语言的威力](ch3-asm/ch3-07-hack-asm.md)
|
||||
* [3.8. 例子:Goroutine ID](ch3-asm/ch3-08-goroutine-id.md)
|
||||
* [3.9. Delve调试器](ch3-asm/ch3-09-debug.md)
|
||||
* [3.10. 补充说明](ch3-asm/ch3-10-ext.md)
|
||||
* [第四章 RPC和Protobuf](ch4-rpc/readme.md)
|
||||
* [4.1. RPC入门](ch4-rpc/ch4-01-rpc-intro.md)
|
||||
* [4.2. Protobuf](ch4-rpc/ch4-02-pb-intro.md)
|
||||
* [4.3. 玩转RPC](ch4-rpc/ch4-03-netrpc-hack.md)
|
||||
* [4.4. GRPC入门](ch4-rpc/ch4-04-grpc.md)
|
||||
* [4.5. GRPC进阶](ch4-rpc/ch4-05-grpc-hack.md)
|
||||
* [4.6. GRPC和Protobuf扩展](ch4-rpc/ch4-06-grpc-ext.md)
|
||||
* [4.7. pbgo: 基于Protobuf的框架](ch4-rpc/ch4-07-pbgo.md)
|
||||
* [4.8. 补充说明](ch4-rpc/ch4-08-ext.md)
|
||||
* [第五章 Go和Web](ch5-web/readme.md)
|
||||
* [5.1. Web开发简介](ch5-web/ch5-01-introduction.md)
|
||||
* [5.2. Router请求路由](ch5-web/ch5-02-router.md)
|
||||
* [5.3. Middleware中间件](ch5-web/ch5-03-middleware.md)
|
||||
* [5.4. Validator请求校验](ch5-web/ch5-04-validator.md)
|
||||
* [5.5. Database和数据库打交道](ch5-web/ch5-05-database.md)
|
||||
* [5.6. Ratelimit 服务流量限制](ch5-web/ch5-06-ratelimit.md)
|
||||
* [5.7. Layout大型web项目分层](ch5-web/ch5-07-layout-of-web-project.md)
|
||||
* [5.8. interface 和 table-driven 开发](ch5-web/ch5-08-interface-and-web.md)
|
||||
* [5.9. 灰度发布和 A/B test](ch5-web/ch5-09-gated-launch.md)
|
||||
* [5.11. Load-balance负载均衡](ch5-web/ch5-11-load-balance.md)
|
||||
* [第六章 分布式系统](ch6-cloud/readme.md)
|
||||
* [6.1. 云上地鼠(TODO)](ch6-cloud/ch6-01-cloud.md)
|
||||
* [6.2. 分布式搜索引擎](ch6-cloud/ch6-02-search-engine.md)
|
||||
* [6.2. Raft协议(TODO)](ch6-cloud/ch6-03-raft.md)
|
||||
* [6.4. 分布式队列(TODO)](ch6-cloud/ch6-04-queue.md)
|
||||
* [6.5. 分布式缓存(TODO)](ch6-cloud/ch6-05-cache.md)
|
||||
* [6.6. etcd(TODO)](ch6-cloud/ch6-06-etcd.md)
|
||||
* [6.7. 分布式 id 生成器](ch6-cloud/ch6-07-dist-id.md)
|
||||
* [6.8. 分布式锁(Doing)](ch6-cloud/ch6-08-lock.md)
|
||||
* [6.9. 分布式任务调度系统(TODO)](ch6-cloud/ch6-09-sched.md)
|
||||
* [6.10. 延时任务系统](ch6-cloud/ch6-10-delay-job.md)
|
||||
* [6.12. 补充说明(TODO)](ch6-cloud/ch6-11-faq.md)
|
||||
* [第1章 语言基础](ch1-basic/readme.md)
|
||||
* [1.1 Go语言创世纪](ch1-basic/ch1-01-genesis.md)
|
||||
* [1.2 Hello, World 的革命](ch1-basic/ch1-02-hello-revolution.md)
|
||||
* [1.3 数组、字符串和切片](ch1-basic/ch1-03-array-string-and-slice.md)
|
||||
* [1.4 函数、方法和接口](ch1-basic/ch1-04-func-method-interface.md)
|
||||
* [1.5 面向并发的内存模型](ch1-basic/ch1-05-mem.md)
|
||||
* [1.6 常见的并发模式](ch1-basic/ch1-06-goroutine.md)
|
||||
* [1.7 错误和异常](ch1-basic/ch1-07-error-and-panic.md)
|
||||
* [1.8 补充说明](ch1-basic/ch1-08-ext.md)
|
||||
* [第2章 CGO编程](ch2-cgo/readme.md)
|
||||
* [2.1 快速入门](ch2-cgo/ch2-01-hello-cgo.md)
|
||||
* [2.2 CGO基础](ch2-cgo/ch2-02-basic.md)
|
||||
* [2.3 类型转换](ch2-cgo/ch2-03-cgo-types.md)
|
||||
* [2.4 函数调用](ch2-cgo/ch2-04-func.md)
|
||||
* [2.5 内部机制](ch2-cgo/ch2-05-internal.md)
|
||||
* [2.6 实战: 封装qsort](ch2-cgo/ch2-06-qsort.md)
|
||||
* [2.7 CGO内存模型](ch2-cgo/ch2-07-memory.md)
|
||||
* [2.8 C++类包装](ch2-cgo/ch2-08-class.md)
|
||||
* [2.9 静态库和动态库](ch2-cgo/ch2-09-static-shared-lib.md)
|
||||
* [2.10 编译和链接参数](ch2-cgo/ch2-10-link.md)
|
||||
* [2.11 补充说明](ch2-cgo/ch2-11-ext.md)
|
||||
* [第3章 汇编语言](ch3-asm/readme.md)
|
||||
* [3.1 快速入门](ch3-asm/ch3-01-basic.md)
|
||||
* [3.2 计算机结构](ch3-asm/ch3-02-arch.md)
|
||||
* [3.3 常量和全局变量](ch3-asm/ch3-03-const-and-var.md)
|
||||
* [3.4 函数](ch3-asm/ch3-04-func.md)
|
||||
* [3.5 控制流](ch3-asm/ch3-05-control-flow.md)
|
||||
* [3.6 再论函数](ch3-asm/ch3-06-func-again.md)
|
||||
* [3.7 汇编语言的威力](ch3-asm/ch3-07-hack-asm.md)
|
||||
* [3.8 例子:Goroutine ID](ch3-asm/ch3-08-goroutine-id.md)
|
||||
* [3.9 Delve调试器](ch3-asm/ch3-09-debug.md)
|
||||
* [3.10 补充说明](ch3-asm/ch3-10-ext.md)
|
||||
* [第4章 RPC和Protobuf](ch4-rpc/readme.md)
|
||||
* [4.1 RPC入门](ch4-rpc/ch4-01-rpc-intro.md)
|
||||
* [4.2 Protobuf](ch4-rpc/ch4-02-pb-intro.md)
|
||||
* [4.3 玩转RPC](ch4-rpc/ch4-03-netrpc-hack.md)
|
||||
* [4.4 GRPC入门](ch4-rpc/ch4-04-grpc.md)
|
||||
* [4.5 GRPC进阶](ch4-rpc/ch4-05-grpc-hack.md)
|
||||
* [4.6 GRPC和Protobuf扩展](ch4-rpc/ch4-06-grpc-ext.md)
|
||||
* [4.7 pbgo: 基于Protobuf的框架](ch4-rpc/ch4-07-pbgo.md)
|
||||
* [4.8 补充说明](ch4-rpc/ch4-08-ext.md)
|
||||
* [第5章 Go和Web](ch5-web/readme.md)
|
||||
* [5.1 Web开发简介](ch5-web/ch5-01-introduction.md)
|
||||
* [5.2 Router请求路由](ch5-web/ch5-02-router.md)
|
||||
* [5.3 Middleware中间件](ch5-web/ch5-03-middleware.md)
|
||||
* [5.4 Validator请求校验](ch5-web/ch5-04-validator.md)
|
||||
* [5.5 Database和数据库打交道](ch5-web/ch5-05-database.md)
|
||||
* [5.6 Ratelimit 服务流量限制](ch5-web/ch5-06-ratelimit.md)
|
||||
* [5.7 Layout大型web项目分层](ch5-web/ch5-07-layout-of-web-project.md)
|
||||
* [5.8 interface 和 table-driven 开发](ch5-web/ch5-08-interface-and-web.md)
|
||||
* [5.9 灰度发布和 A/B test](ch5-web/ch5-09-gated-launch.md)
|
||||
* [5.11 Load-balance负载均衡](ch5-web/ch5-11-load-balance.md)
|
||||
* [第6章 分布式系统](ch6-cloud/readme.md)
|
||||
* [6.1 云上地鼠(TODO)](ch6-cloud/ch6-01-cloud.md)
|
||||
* [6.2 分布式搜索引擎](ch6-cloud/ch6-02-search-engine.md)
|
||||
* [6.2 Raft协议(TODO)](ch6-cloud/ch6-03-raft.md)
|
||||
* [6.4 分布式队列(TODO)](ch6-cloud/ch6-04-queue.md)
|
||||
* [6.5 分布式缓存(TODO)](ch6-cloud/ch6-05-cache.md)
|
||||
* [6.6 etcd(TODO)](ch6-cloud/ch6-06-etcd.md)
|
||||
* [6.7 分布式 id 生成器](ch6-cloud/ch6-07-dist-id.md)
|
||||
* [6.8 分布式锁(Doing)](ch6-cloud/ch6-08-lock.md)
|
||||
* [6.9 分布式爬虫(TODO)](ch6-cloud/ch6-09-scrawler.md)
|
||||
* [6.10 延时任务系统](ch6-cloud/ch6-10-delay-job.md)
|
||||
* [6.11 补充说明(TODO)](ch6-cloud/ch6-11-faq.md)
|
||||
* [附录](appendix/readme.md)
|
||||
* [附录A: Go语言常见坑](appendix/appendix-a-trap.md)
|
||||
* [附录B: 有趣的代码片段](appendix/appendix-b-gems.md)
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 1.1. Go语言创世纪
|
||||
# 1.1 Go语言创世纪
|
||||
|
||||
Go语言最初由Google公司的Robert Griesemer、Ken Thompson和Rob Pike三个大牛于2007年开始设计发明,设计新语言的最初的洪荒之力来自于对超级复杂的C++11特性的吹捧报告的鄙视,最终的目标是设计网络和多核时代的C语言。到2008年中期,语言的大部分特性设计已经完成,并开始着手实现编译器和运行时,大约在这一年Russ Cox作为主力开发者加入。到了2010年,Go语言已经逐步趋于稳定,并在9月正式发布Go语言并开源了代码。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 1.2. Hello, World 的革命
|
||||
# 1.2 Hello, World 的革命
|
||||
|
||||
在创世纪章节中我们简单介绍了Go语言的演化基因族谱,对其中来自于贝尔实验室的特有并发编程基因做了重点介绍,最后引出了Go语言版的“Hello, World”程序。其实“Hello, World”程序是展示各种语言特性的最好的例子,是通向该语言的一个窗口。这一节我们将沿着各个编程语言演化的时间轴,简单回顾下“Hello, World”程序是如何逐步演化到目前的Go语言形式、最终完成它的革命使命的。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 1.3. 数组、字符串和切片
|
||||
# 1.3 数组、字符串和切片
|
||||
|
||||
在主流的编程语言中数组及其相关的数据结构是使用得最为频繁的,只有在它(们)不能满足时才会考虑链表、hash表(hash表可以看作是数组和链表的混合体)和更复杂的自定义数据结构。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 1.4. 函数、方法和接口
|
||||
# 1.4 函数、方法和接口
|
||||
|
||||
函数对应操作序列,是程序的基本组成元素。Go语言中的函数有具名和匿名之分:具名函数一般对应于包级的函数,是匿名函数的一种特例,当匿名函数引用了外部作用域中的变量时就成了闭包函数,闭包函数是函数式编程语言的核心。方法是绑定到一个具体类型的特殊函数,Go语言中的方法是依托于类型的,必须在编译时静态绑定。接口定义了方法的集合,这些方法依托于运行时的接口对象,因此接口对应的方法是在运行时动态绑定的。Go语言通过隐式接口机制实现了鸭子面向对象模型。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 1.5. 面向并发的内存模型
|
||||
# 1.5 面向并发的内存模型
|
||||
|
||||
在早期,CPU都是以单核的形式顺序执行机器指令。Go语言的祖先C语言正是这种顺序编程语言的代表。顺序编程语言中的顺序是指:所有的指令都是以串行的方式执行,在相同的时刻有且仅有一个CPU在顺序执行程序的指令。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 1.6. 常见的并发模式
|
||||
# 1.6 常见的并发模式
|
||||
|
||||
Go语言最吸引人的地方是它内建的并发支持。Go语言并发体系的理论是C.A.R Hoare在1978年提出的CSP(Communicating Sequential Process,通讯顺序进程)。CSP有着精确的数学模型,并实际应用在了Hoare参与设计的T9000通用计算机上。从NewSqueak、Alef、Limbo到现在的Go语言,对于对CSP有着20多年实战经验的Rob Pike来说,他更关注的是将CSP应用在通用编程语言上的潜力。作为Go并发编程核心的CSP理论的核心概念只有一个:同步通信。关于同步通信的话题我们在前面一节已经讲过,本节我们将简单介绍下Go语言中常见的并发模式。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 1.7. 错误和异常
|
||||
# 1.7 错误和异常
|
||||
|
||||
错误处理是每个编程语言都要考虑的一个重要话题。在Go语言的错误处理中,错误是软件包API和应用程序用户界面的一个重要组成部分。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
## 1.8. 补充说明
|
||||
## 1.8 补充说明
|
||||
|
||||
本书定位是Go语言进阶图书,因此读者需要有一定的Go语言基础。如果对Go语言不太了解,作者推荐通过以下资料开始学习Go语言。首先是安装Go语言环境,然后通过`go tool tour`命令打开“A Tour of Go”教程学习。在学习“A Tour of Go”教程的同时,可以阅读Go语言官方团队出版的[《The Go Programming Language》](http://www.gopl.io/)教程。[《The Go Programming Language》](http://www.gopl.io/)在国内Go语言社区被称为Go语言圣经,它将带你系统地学习Go语言。在学习的同时可以尝试用Go语言解决一些小问题,如果遇到要差异API的适合可以通过godoc命令打开自带的文档查询。Go语言本身不仅仅包含了所有的文档,也包含了所有标准库的实现代码,这是第一手的最权威的Go语言资料。我们此时你应该已经可以熟练使用Go语言了。
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
# 第一章 语言基础
|
||||
# 第1章 语言基础
|
||||
|
||||
本章首先简要介绍Go语言的发展历史,并较详细地分析了“Hello World”程序在各个祖先语言中演化过程。然后,对以数组、字符串和切片为代表的基础结构,对以函数、方法和接口所体现的面向过程和鸭子对象的编程,以及Go语言特有的并发编程模型和错误处理哲学做了简单介绍。最后,针对macOS、Windows、Linux几个主流的开发平台,推荐了几个较友好的Go语言编辑器和集成开发环境,因为好的工具可以极大地提高我们的效率。
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 2.1. 快速入门
|
||||
# 2.1 快速入门
|
||||
|
||||
本节我们将通过由浅入深的一系列小例子来快速掌握CGO的基本用法。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 2.2. CGO基础
|
||||
# 2.2 CGO基础
|
||||
|
||||
要使用CGO特性,需要安装C/C++构建工具链,在macOS和Linux下是要安装GCC,在windows下是需要安装MinGW工具。同时需要保证环境变量`CGO_ENABLED`被设置为1,这表示CGO是被启用的状态。在本地构建时`CGO_ENABLED`默认是启用的,当交叉构建时CGO默认是禁止的。比如要交叉构建ARM环境运行的Go程序,需要手工设置好C/C++交叉构建的工具链,同时开启`CGO_ENABLED`环境变量。然后通过`import "C"`语句启用CGO特性。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 2.3. 类型转换
|
||||
# 2.3 类型转换
|
||||
|
||||
最初CGO是为了达到方便从Go语言函数调用C语言函数以复用C语言资源这一目的而出现的(因为C语言还会涉及回调函数,自然也会涉及到从C语言函数调用Go语言函数)。现在,它已经演变为C语言和Go语言双向通讯的桥梁。要想利用好CGO特性,自然需要了解此二语言类型之间的转换规则,这是本节要讨论的问题。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 2.4. 函数调用
|
||||
# 2.4 函数调用
|
||||
|
||||
函数是C语言编程的核心,通过CGO技术我们不仅仅可以在Go语言中调用C语言函数,也可以将Go语言函数导出为C语言函数。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 2.5. 内部机制
|
||||
# 2.5 内部机制
|
||||
|
||||
对于刚刚接触CGO用户来说,CGO的很多特性类似魔法。CGO特性主要是通过一个叫cgo的命令行工具来辅助输出Go和C之间的桥接代码。本节我们尝试从生成的代码分析Go语言和C语言函数直接相互调用的流程。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 2.6. 实战: 封装qsort
|
||||
# 2.6 实战: 封装qsort
|
||||
|
||||
qsort快速排序函数是C语言的高阶函数,支持用于自定义排序比较函数,可以对任意类型的数组进行排序。本节我们尝试基于C语言的qsort函数封装一个Go语言版本的qsort函数。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 2.7. CGO内存模型
|
||||
# 2.7 CGO内存模型
|
||||
|
||||
CGO是架接Go语言和C语言的桥梁,它使二者在二进制接口层面实现了互通,但是我们要注意因两种语言的内存模型的差异而可能引起的问题。如果在CGO处理的跨语言函数调用时涉及到了指针的传递,则可能会出现Go语言和C语言共享某一段内存的场景。我们知道C语言的内存在分配之后就是稳定的,但是Go语言因为函数栈的动态伸缩可能导致栈中内存地址的移动(这是Go和C内存模型的最大差异)。如果C语言持有的是移动之前的Go指针,那么以旧指针访问Go对象时会导致程序崩溃。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 2.8. C++ 类包装
|
||||
# 2.8 C++ 类包装
|
||||
|
||||
CGO是C语言和Go语言之间的桥梁,原则上无法直接支持C++的类。CGO不支持C++语法的根本原因是C++至今为止还没有一个二进制接口规范(ABI)。一个C++类的构造函数在编译为目标文件时如何生成链接符号名称、方法在不同平台甚至是C++的不同版本之间都是不一样的。但是C++是兼容C语言,所以我们可以通过增加一组C语言函数接口作为C++类和CGO之间的桥梁,这样就可以间接地实现C++和Go之间的互联。当然,因为CGO只支持C语言中值类型的数据类型,所以我们是无法直接使用C++的引用参数等特性的。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 2.9. 静态库和动态库
|
||||
# 2.9 静态库和动态库
|
||||
|
||||
CGO在使用C/C++资源的时候一般有三种形式:直接使用源码;链接静态库;链接动态库。直接使用源码就是在`import "C"`之前的注释部分包含C代码,或者在当前包中包含C/C++源文件。链接静态库和动态库的方式比较类似,都是通过在LDFLAGS选项指定要链接的库方式链接。本节我们主要关注在CGO中如何使用静态库和动态库相关的问题。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 2.10. 编译和链接参数
|
||||
# 2.10 编译和链接参数
|
||||
|
||||
编译和链接参数是每一个C/C++程序员需要经常面对的问题。构建每一个C/C++应用均需要经过编译和链接两个步骤,CGO也是如此。
|
||||
本节我们将简要讨论CGO中经常用到的编译和链接参数的用法。
|
||||
|
@ -1,4 +1,4 @@
|
||||
## 2.11. 补充说明
|
||||
## 2.11 补充说明
|
||||
|
||||
CGO是C语言和Go语言混合编程的技术,因此要想熟练地使用CGO需要了解这两门语言。C语言推荐两本书:第一本是C语言之父编写的《C程序设计语言》;第二本是讲述C语言模块化编程的《C语言接口与实现:创建可重用软件的技术》。Go语言推荐官方出版的《The Go Programming Language》和Go语言自带的全部文档和全部代码。
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
# 第二章 CGO编程
|
||||
# 第2章 CGO编程
|
||||
|
||||
C/C++经过几十年的发展,已经积累了庞大的软件资产,它们很多久经考验而且性能已经足够优化。Go语言必须能够站在C/C++这个巨人的肩膀之上,有了海量的C/C++软件资产兜底之后,我们才可以放心愉快地用Go语言编程。C语言作为一个通用语言,很多库会选择提供一个C兼容的API,然后用其他不同的编程语言实现。Go语言通过自带的一个叫CGO的工具来支持C语言函数调用,同时我们可以用Go语言导出C动态库接口给其它语言使用。本章主要讨论CGO编程中涉及的一些问题。
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 3.1. 快速入门
|
||||
# 3.1 快速入门
|
||||
|
||||
Go汇编程序始终是幽灵一样的存在。我们将通过分析简单的Go程序输出的汇编代码,然后照猫画虎用汇编实现一个简单的输出程序。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 3.2. 计算机结构
|
||||
# 3.2 计算机结构
|
||||
|
||||
汇编语言是直面计算机的编程语言,因此理解计算机结构是掌握汇编语言的前提。当前流行的计算机基本采用的是冯·诺伊曼计算机体系结构(在某些特殊领域还有哈佛体系架构)。冯·诺依曼结构也称为普林斯顿结构,采用的是一种将程序指令和数据存储在一起的存储结构。冯·诺伊曼计算机中的指令和数据存储器其实指的是计算机中的内存,然后在配合CPU处理器就组成了一个最简单的计算机了。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 3.3. 常量和全局变量
|
||||
# 3.3 常量和全局变量
|
||||
|
||||
程序中的一切变量的初始值都直接或间接地依赖常量或常量表达式生成。在Go语言中很多变量是默认零值初始化的,但是Go汇编中定义的变量最好还是手工通过常量初始化。有了常量之后,就可以衍生定义全局变量,并使用常量组成的表达式初始化其它各种变量。本节将简单讨论Go汇编语言中常量和全局变量的用法。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 3.4. 函数
|
||||
# 3.4 函数
|
||||
|
||||
终于到函数了!因为Go汇编语言中,可以也建议通过Go语言来定义全局变量,那么剩下的也就是函数了。只有掌握了汇编函数的基本用法,才能真正算是Go汇编语言入门。本章将简单讨论Go汇编中函数的定义和用法。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 3.5. 控制流
|
||||
# 3.5 控制流
|
||||
|
||||
程序主要有顺序、分支和循环几种执行流程。本节主要讨论如何将Go语言的控制流比较直观地转译为汇编程序,或者说如何以汇编思维来编写Go语言代码。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 3.6. 再论函数
|
||||
# 3.6 再论函数
|
||||
|
||||
在前面的章节中我们已经简单讨论过Go的汇编函数,但是那些主要是叶子函数。叶子函数的最大特点是不会调用其他函数,也就是栈的大小是可以预期的,叶子函数也就是可以基本忽略爆栈的问题(如果已经爆了,那也是上级函数的问题)。如果没有爆栈问题,那么也就是不会有栈的分裂问题;如果没有栈的分裂也就不需要移动栈上的指针,也就不会有栈上指针管理的问题。但是是现实中Go语言的函数是可以任意深度调用的,永远不用担心爆栈的风险。那么这些近似黑科技的特性是如何通过低级的汇编语言实现的呢?这些都是本节尝试讨论的问题。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 3.7. 汇编语言的威力
|
||||
# 3.7 汇编语言的威力
|
||||
|
||||
汇编语言的真正威力来自两个维度:一是突破框架限制,实现看似不可能的任务;二是突破指令限制,通过高级指令挖掘极致的性能。对于第一个问题,我们将演示如何通过Go汇编语言直接访问系统调用,和直接调用C语言函数。对于第二个问题,我们将演示X64指令中AVX等高级指令的简单用法。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 3.8. 例子:Goroutine ID
|
||||
# 3.8 例子:Goroutine ID
|
||||
|
||||
在操作系统中,每个进程都会有一个唯一的进程编号,每个线程也有自己唯一的线程编号。同样在Go语言中,每个Goroutine也有自己唯一的Go程编号,这个编号在panic等场景下经常遇到。虽然Goroutine有内在的编号,但是Go语言却刻意没有提供获取该编号的接口。本节我们尝试通过Go汇编语言获取Goroutine ID。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 3.9. Delve调试器
|
||||
# 3.9 Delve调试器
|
||||
|
||||
目前Go语言支持GDB、LLDB和Delve几种调试器。其中GDB是最早支持的调试工具,LLDB是macOS系统推荐的标准调试工具。但是GDB和LLDB对Go语言的专有特性都缺乏很大支持,而只有Delve是专门为Go语言设计开发的调试工具。而且Delve本身也是采用Go语言开发,对Windows平台也提供了一样的支持。本节我们基于Delve简单解释如何调试Go汇编程序。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
## 3.10. 补充说明
|
||||
## 3.10 补充说明
|
||||
|
||||
如果是纯粹学习汇编语言,则可以从《深入理解程序设计:使用Linux汇编语言》开始,该书讲述了如何以C语言的思维变现汇编程序。如果是学习X86汇编,则可以从《汇编语言:基于x86处理器》一开始,然后再结合《现代x86汇编语言程序设计》学习AVX等高级汇编指令的使用。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 第三章 Go汇编语言
|
||||
# 第3章 Go汇编语言
|
||||
|
||||
Go语言中很多设计思想和工具都是传承自Plan9操作系统,Go汇编语言也是基于Plan9汇编演化而来。根据Rob Pike的介绍,大神Ken Thompson在1986年为Plan9系统编写的C语言编译器输出的汇编伪代码就是Plan9汇编的前身。所谓的Plan9汇编语言只是便于以手工方式书写该C语言编译器输出的汇编伪代码而已。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 4.1. RPC入门
|
||||
# 4.1 RPC入门
|
||||
|
||||
RPC是远程过程调用的简称,是分布式系统中不同节点间流行的通信方式。在互联网时代,RPC已经和IPC一样成为一个不可或缺的基础构件。因此Go语言的标准库也提供了一个简单的RPC实现,我们将以此为入口学习RPC的各种用法。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 4.2. Protobuf
|
||||
# 4.2 Protobuf
|
||||
|
||||
Protobuf是Protocol Buffers的简称,它是Google公司开发的一种数据描述语言,并于2008年对外开源。Protobuf刚开源时的定位类似于XML、JSON等数据描述语言,通过附带工具生成代码并实现将结构化数据序列化的功能。但是我们更关注的是Protobuf作为接口规范的描述语言,可以作为设计安全的跨语言PRC接口的基础工具。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 4.3. 玩转RPC
|
||||
# 4.3 玩转RPC
|
||||
|
||||
在不同的场景中RPC有着不同的需求,因此开源的社区就诞生了各种RPC框架。本节我们将尝试Go内置RPC框架在一些比较特殊场景的用法。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 4.4. GRPC入门
|
||||
# 4.4 GRPC入门
|
||||
|
||||
GRPC是Google公司基于Protobuf开发的跨语言的开源RPC框架。GRPC基于HTTP/2协议设计,可以基于一个HTTP/2链接提供多个服务,对于移动设备更加友好。本节将讲述GRPC的简单用法。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 4.5. GRPC进阶
|
||||
# 4.5 GRPC进阶
|
||||
|
||||
作为一个基础的RPC框架,安全和扩展是经常遇到的问题。本节将简单介绍如何对GRPC进行安全认证。然后介绍通过GRPC的截取器特性,以及如何通过截取器优雅地实现Token认证、调用跟踪以及Panic捕获等特性。最后介绍了GRPC服务如何和其他Web服务共存。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 4.6. GRPC和Protobuf扩展
|
||||
# 4.6 GRPC和Protobuf扩展
|
||||
|
||||
目前开源社区已经围绕Protobuf和GRPC开发出众多扩展,形成了庞大的生态。本节我们将简单介绍验证器和REST接口扩展。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 4.7. pbgo: 基于Protobuf的框架
|
||||
# 4.7 pbgo: 基于Protobuf的框架
|
||||
|
||||
pbgo是我们专门针对本节内容设计的较为完整的迷你框架,它基于Protobuf的扩展语法,通过插件自动生成rpc和rest相关代码。在本章第二节我们已经展示过如何定制一个Protobuf代码生成插件,并生成了rpc部分的代码。在本节我们将重点讲述pbgo中和Protobuf扩展语法相关的rest部分的工作原理。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
## 4.8. 补充说明
|
||||
## 4.8 补充说明
|
||||
|
||||
目前专门讲述RPC的图书比较少。目前Protobuf和GRPC的官网都提供了详细的参考资料和例子。本章重点讲述了Go标准库的RPC和基于Protobuf衍生的GRPC框架,同时也简单展示了如何自己定制一个RPC框架。之所以聚焦在这几个有限的主题,是因为这几个技术都是Go语言团队官方在进行维护,和Go语言契合也最为默契。不过RPC依然是一个庞大的主题,足以单独成书。目前开源世界也有很多富有特色的RPC框架,还有针对分布式系统进行深度定制的RPC系统,用户可以根据自己实际需求选择合适的工具。
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
# 第四章 RPC和Protobuf
|
||||
# 第4章 RPC和Protobuf
|
||||
|
||||
RPC是远程过程调用的缩写(Remote Procedure Call),通俗地说就是调用远处的一个函数。远处到底有多远呢?可能是同一个文件内的不同函数,也可能是同一个机器的另一个进程的函数,还可能是远在火星好奇号上面的某个秘密方法。因为RPC涉及的函数可能非常之远,远到它们之间说着完全不同的语言,语言就成了两边的沟通障碍。而Protobuf因为支持多种不同的语言(甚至不支持的语言也可以扩展支持),其本身特性也非常方便描述服务的接口(也就是方法列表),因此非常适合作为RPC世界的接口交流语言。本章将讨论RPC的基本用法,如何针对不同场景设计自己的RPC服务,以及围绕Protobuf构造的更为庞大的RPC生态。
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 5.1. web 开发简介
|
||||
# 5.1 web 开发简介
|
||||
|
||||
由于 golang 的 `net/http` 提供了基础的路由函数组合,并且也提供了丰富的功能函数。所以在 golang 社区里有一种观点认为用 golang 写 api 不需要框架。其看法也存在一定的道理,如果你的项目路由在个位数,URI 固定且不通过 URI 来传递参数,那么使用官方库也就足够。但在复杂场景下,官方的 http 库还是有些力不从心。例如下面这样的路由:
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 5.2. router 请求路由
|
||||
# 5.2 router 请求路由
|
||||
|
||||
在常见的 web 框架中,router 是必备的组件。golang 圈子里 router 也时常被称为 http 的 multiplexer。在上一节中我们通过对 Burrow 代码的简单学习,已经知道如何用 http 标准库中内置的 mux 来完成简单的路由功能了。如果开发 web 系统对路径中带参数没什么兴趣的话,用 http 标准库中的 mux 就可以。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 5.3. middleware 中间件
|
||||
# 5.3 middleware 中间件
|
||||
|
||||
本章将对现在流行的 web 框架中的中间件技术原理进行分析,并介绍如何使用中间件技术将业务和非业务代码功能进行解耦。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 5.4. validator 请求校验
|
||||
# 5.4 validator 请求校验
|
||||
|
||||
社区里曾经有人用这张图来嘲笑 PHP:
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 5.5. Database 和数据库打交道
|
||||
# 5.5 Database 和数据库打交道
|
||||
|
||||
本节将对 db/sql 官方标准库作一些简单分析,并介绍一些应用比较广泛的开源 orm 和 sql builder。并从企业级应用开发和公司架构的角度来分析哪种技术栈对于现代的企业级应用更为合适。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 5.6. Ratelimit 服务流量限制
|
||||
# 5.6 Ratelimit 服务流量限制
|
||||
|
||||
计算机程序可依据其瓶颈分为 Disk IO-bound,CPU-bound,Network-bound,分布式场景下有时候也会外部系统而导致自身瓶颈。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 5.7. layout 常见大型 web 项目分层
|
||||
# 5.7 layout 常见大型 web 项目分层
|
||||
|
||||
流行的 web 框架大多数是 MVC 框架,MVC 这个概念最早由 Trygve Reenskaug 在 1978 年提出,为了能够对 GUI 类型的应用进行方便扩展,将程序划分为:
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 5.8. interface 和 table-driven 开发
|
||||
# 5.8 interface 和 table-driven 开发
|
||||
|
||||
在 web 项目中经常会遇到外部依赖环境的变化,比如:
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 5.9. 灰度发布和 A/B test
|
||||
# 5.9 灰度发布和 A/B test
|
||||
|
||||
中型的互联网公司往往有着以百万计的用户,而大型互联网公司的系统则可能要服务千万级甚至亿级的用户需求。大型系统的请求流入往往是源源不断的,任何风吹草动,都一定会有最终用户感受得到。例如你的系统在上线途中会拒绝一些上游过来的请求,而这时候依赖你的系统没有做任何容错,那么这个错误就会一直向上抛出,直到触达最终用户。形成一次对用户切切实实的伤害。这种伤害可能是在用户的 app 上弹出一个让用户摸不着头脑的诡异字符串,用户只要刷新一下页面就可以忘记这件事。但也可能会让正在心急如焚地和几万竞争对手同时抢夺秒杀商品的用户,因为代码上的小问题,丧失掉了先发优势,与自己蹲了几个月的心仪产品失之交臂。对用户的伤害有多大,取决于你的系统对于你的用户来说有多重要。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 5.10. Service Discovery 服务发现
|
||||
# 5.10 Service Discovery 服务发现
|
||||
|
||||
在微服务架构中,服务之间是存在依赖的。例如在订单系统中创建订单时,需要对用户信息做快照,这时候也就意味着这个流程要依赖: 订单、用户两个系统。当前大型网站的语境下,多服务分布式共存,单个服务也可能会跑在多台物理/虚拟机上。所以即使你知道你需要依赖的是“订单服务”这个具体的服务,实际面对的仍然是多个 ip+port 组成的集群。因此你需要: 1. 通过“订单服务”这个名字找到它对应的 ip+port 列表;2. 决定把这个请求发到哪一个 ip+port 上的订单服务。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 5.11. Load-Balance 负载均衡
|
||||
# 5.11 Load-Balance 负载均衡
|
||||
|
||||
本节将会讨论常见的 web 后端服务之间的负载均衡手段。
|
||||
|
||||
|
@ -1 +1 @@
|
||||
# 5.12. Dist-config 分布式配置服务
|
||||
# 5.12 Dist-config 分布式配置服务
|
||||
|
@ -1 +1 @@
|
||||
# 5.13. Circuit-Breaker 熔断保护
|
||||
# 5.13 Circuit-Breaker 熔断保护
|
||||
|
@ -1 +1 @@
|
||||
# 5.8. Monitor metrics 和服务监控
|
||||
# 5.14 Monitor metrics 和服务监控
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 第五章 go 和 web
|
||||
# 第5章 go 和 web
|
||||
|
||||
本章将会阐述 go 在 web 开发方面的现状,并以几个典型的开源 web 框架为例,带大家深入 web 框架本身的执行流程。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 6.1. 云上地鼠
|
||||
# 6.1 云上地鼠
|
||||
|
||||
从 2014 年 docker 诞生开始,Go 语言开始在分布式领域崭露头角,之后 k8s,kong,groupcache,nats,etcd,tidb 让人们不断看到了 Go 在分布式领域的新的可能性。目前在大部分的分布式场景下,Go 语言都有相应的产品,无论是存储,rpc 框架,消息队列等等。Go 被称为分布式时代的 C 语言着实所言非虚。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 6.2. 分布式搜索引擎
|
||||
# 6.2 分布式搜索引擎
|
||||
|
||||
在 web 一章中,我们提到 MySQL 很脆弱。数据库系统本身要保证实时和强一致性,所以其功能设计上都是为了满足这种一致性需求。比如 write ahead log 的设计,基于 B+ 树实现的索引和数据组织,以及基于 MVCC 实现的事务等等。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 6.3. Raft协议
|
||||
# 6.3 Raft协议
|
||||
|
||||
raft 是一种分布式一致性算法,其能够保证在 2n+1 的系统,有 n+1 以上的节点存活时,向集群中写入的数据保证不会丢失。相比 paxos,其有更好的易读性和简洁性,所以从诞生起便受到很多人的赞许。该算法与 paxos 类似,被广泛应用于分布式调度的元信息存储,或在存储领域进行日志复制。
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
# 6.4. 分布式队列
|
||||
# 6.4 分布式队列
|
||||
|
||||
TODO
|
||||
|
@ -1,3 +1,3 @@
|
||||
# 6.5. 分布式缓存
|
||||
# 6.5 分布式缓存
|
||||
|
||||
TODO
|
||||
|
@ -1,3 +1,3 @@
|
||||
# 6.6. etcd
|
||||
# 6.6 etcd
|
||||
|
||||
TODO
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 6.7. 分布式 id 生成器
|
||||
# 6.7 分布式 id 生成器
|
||||
|
||||
有时我们需要能够生成类似 MySQL 自增 ID 这样不断增大,同时又不会重复的 id。以支持业务中的高并发场景。比较典型的,电商促销时,短时间内会有大量的订单涌入到系统,比如每秒 10w+。明星出轨时,会有大量热情的粉丝发微薄以表心意,同样产生短时间大量的消息。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 6.8. 分布式锁
|
||||
# 6.8 分布式锁
|
||||
|
||||
在单机程序并发或并行修改全局变量时,需要对修改行为加锁以创造临界区。为什么需要加锁呢?可以看看下段代码:
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 6.9. 分布式爬虫
|
||||
# 6.9 分布式爬虫
|
||||
|
||||
## 基于 colly 的单机爬虫
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 6.10. 延时任务系统
|
||||
# 6.10 延时任务系统
|
||||
|
||||
我们在做系统时,很多时候是处理实时的任务,请求来了马上就处理,然后立刻给用户以反馈。但有时也会遇到非实时的任务,比如确定的时间点发布重要公告。或者需要在用户做了一件事情的 X 分钟/Y 小时后,对其特殊动作,比如通知、发券等等。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 6.12. 补充说明
|
||||
# 6.11. 补充说明
|
||||
|
||||
分布式是很大的领域,本章中的介绍只能算是对领域的管中窥豹。因为大型系统流量大,并发高,所以往往很多朴素的方案会变得难以满足需求。人们为了解决大型系统场景中的各种问题,而开发出了各式各样的分布式系统。有些系统非常简单,比如本章中介绍的分布式 id 生成器,而有一些系统则可能非常复杂,比如本章中的分布式搜索引擎(当然,本章中提到的 es 不是 Go 实现)。
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 第六章 分布式系统
|
||||
# 第6章 分布式系统
|
||||
|
||||
Go语言号称是互联网时代的C语言。现在的互联网系统已经不是以前的一个主机搞定一切的时代,互联网时代的服务后台有大量的分布式系统构成,任何单一后台服务器节点的故障并不会导致整个系统的停机。同时以青云、阿里云、腾讯云为代表的云厂商崛起标志着云时代的到来,在云时代分布式编程将成为一个基本技能。而基于Go语言构建的Docker、K8s等系统正是推动了云时代的提前到来。
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user