Go语言高级编程 (chai2010 [chai2010]) (Z-Library)
Statistics
3
Views
0
Downloads
0
Donations
Uploader

高宏飞

Shared on 2025年12月14日
Actions

Go语言高级编程 (chai2010 [chai2010]) (Z-Library)

技术

Authorchai2010 [chai2010]

本书涵盖CGO、Go汇编语言、RPC实现、Web框架实现、分布式系统等高阶主题,针对Go语言有一定经验想深入了解Go语言各种高级用法的开发人员。

Publisher: GitBook
Publish Year: 2018
Language: 英文
File Format: PDF
File Size: 6.1 MB
Support Statistics
¥.00 · 0times
Text Preview (First 20 pages)
Registered users can read the full content for free

Register as a Gaohf Library member to read the complete e-book online for free and enjoy a better reading experience.

(This page has no text content)
目录 1. Introduction 1.1 2. 第1章 语言基础 1.2 1. 1.1 Go语言创世纪 1.2.1 2. 1.2 Hello, World 的革命 1.2.2 3. 1.3 数组、字符串和切片 1.2.3 4. 1.4 函数、方法和接口 1.2.4 5. 1.5 面向并发的内存模型 1.2.5 6. 1.6 常见的并发模式 1.2.6 7. 1.7 错误和异常 1.2.7 8. 1.8 补充说明 1.2.8 3. 第2章 CGO编程 1.3 1. 2.1 快速入门 1.3.1 2. 2.2 CGO基础 1.3.2 3. 2.3 类型转换 1.3.3 4. 2.4 函数调用 1.3.4 5. 2.5 内部机制 1.3.5 6. 2.6 实战: 封装qsort 1.3.6
7. 2.7 CGO内存模型 1.3.7 8. 2.8 C++类包装 1.3.8 9. 2.9 静态库和动态库 1.3.9 10. 2.10 编译和链接参数 1.3.10 11. 2.11 补充说明 1.3.11 4. 第3章 汇编语言 1.4 1. 3.1 快速入门 1.4.1 2. 3.2 计算机结构 1.4.2 3. 3.3 常量和全局变量 1.4.3 4. 3.4 函数 1.4.4 5. 3.5 控制流 1.4.5 6. 3.6 再论函数 1.4.6 7. 3.7 汇编语言的威力 1.4.7 8. 3.8 例子:Goroutine ID 1.4.8 9. 3.9 Delve调试器 1.4.9 10. 3.10 补充说明 1.4.10 5. 第4章 RPC和Protobuf 1.5 1. 4.1 RPC入门 1.5.1
2. 4.2 Protobuf 1.5.2 3. 4.3 玩转RPC 1.5.3 4. 4.4 GRPC入门 1.5.4 5. 4.5 GRPC进阶 1.5.5 6. 4.6 GRPC和Protobuf扩展 1.5.6 7. 4.7 pbgo: 基于Protobuf的框架 1.5.7 8. 4.8 grpcurl工具 1.5.8 9. 4.9 补充说明 1.5.9 6. 第5章 Go和Web 1.6 1. 5.1 Web开发简介 1.6.1 2. 5.2 Router请求路由 1.6.2 3. 5.3 Middleware中间件 1.6.3 4. 5.4 Validator请求校验 1.6.4 5. 5.5 Database和数据库打交道 1.6.5 6. 5.6 Ratelimit 服务流量限制 1.6.6 7. 5.7 Layout大型web项目分层 1.6.7 8. 5.8 interface 和 table-driven 开发
1.6.8 9. 5.9 灰度发布和 A/B test 1.6.9 10. 5.10 补充说明 1.6.10 7. 第6章 分布式系统 1.7 1. 6.1 分布式 id 生成器 1.7.1 2. 6.2 分布式锁 1.7.2 3. 6.3 延时任务系统 1.7.3 4. 6.4 分布式搜索引擎 1.7.4 5. 6.5 负载均衡 1.7.5 6. 6.6 分布式配置管理 1.7.6 7. 6.7 分布式爬虫 1.7.7 8. 6.8 补充说明 1.7.8 8. 附录 1.8 1. 附录A: Go语言常见坑 1.8.1 2. 附录B: 有趣的代码片段 1.8.2 3. 附录C: 作者简介 1.8.3 Go语言高级编程(Advanced Go Programming)
本书涵盖CGO、Go汇编语言、RPC实现、Web框架实现、分布 式系统等高阶主题,针对Go语言有一定经验想深入了解Go语 言各种高级用法的开发人员。对于刚学习Go语言的读者,建 议先从 《Go语言圣经》 开始系统学习Go语言的基础知识。 作者:柴树杉,Github @chai2010 ,Twitter @chaishushan 作者:曹春晖,Github @cch123
网址: https://github.com/chai2010/advanced-go- programming-book 在线阅读 https://chai2010.cn/advanced-go-programming-book/ https://www.gitbook.com/book/chai2010/advanced-go- programming-book/ 关注微信公众号(golang-china) 版权声明 Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License 。 严禁任何商业行为使用或引用该文档的全部或部分内容! 欢迎大家提供建议!
序言 2009年11月,Google发布了Go语言,在世界范围内引发了轰 动。2015年和2016年中国区的Go语言大会分别在上海和北京 召开,来自Go语言团队的开发人员均作了相关的报告。纵观 这几年来的发展趋势,Go语言已经成为云计算、云存储时代 最重要的基础编程语言。 中国的Go语言社区是全球最大的Go语言社区,我们不仅仅从 一开始就始终紧跟着Go语言的发展脚步,同时也为Go语言的 发展作出了自己的巨大贡献。来自中国深圳的韦光京 (vcc.163@gmail.com)在2010年前后,关于MinGW的工作奠 定了Go语言对Windows平台的支持,同时也奠定了CGO对 Windows平台的支持。同样来自中国的 Minux(minux.ma@gmail.com)则作为Go语言核心团队的成 员,他参与了大量的Go语言核心设计和开发评审工作。同时 还有大量的国内Go语言爱好者积极参与了BUG的汇报和修复 等工作(作者也是其中之一)。 截至2018年,中国出版的Go语言相关教程有近15本之多,内 容主要涵盖Go语言基础编程、Web编程、并发编程和内部源码 剖析等诸多领域。但作为Go语言的资深用户,作者关注的Go 语言话题远远不止这些内容。其中CGO特性实现了Go语言对C 语言和C++语言的支持,使得Go语言可以无缝继承C/C++世界 数十年来积累的巨大软件资产。Go汇编语言更是提供了直接 访问底层机器指令的方法,让我们可以无限压榨程序中热点代 码的性能。目前国内互联网公司的新兴项目已经在逐渐向Go 语言生态转移,大型分布式系统的开发实战经验也是大家关心 的。这些高阶或前沿特性都是作者和本书所关注的话题。 本书针对有一定Go语言经验,想深入了解Go语言各种高级用
法的开发人员。对于Go语言新手,在阅读本书前建议先熟读 D&K的 《The Go Programming Language》 。最后,希望这本 书能够帮助大家更深入地了解Go语言。 chai2010 - 2018年 8 月 于 武汉 致谢 首先感谢Go语言之父和每一个为Go语言提交过补丁的朋友。 感谢fango的第一本以Go语言为主题的网络小说《胡文 Go.ogle》和第一本中文Go语言图书《Go语言·云动力》,是你 的分享让带起了大家学习Go语言的热情。感谢韦光京对 Windows平台CGO的开创性工作,不然本书可能不会有专门的 CGO章节。感谢为本书提交过issue或PR的朋友(特别是 fuwensun、lewgun等),你们的关注和支持是作者写作的最大 动力。 谢谢大家! 第1章 语言基础 本章首先简要介绍Go语言的发展历史,并较详细地分析 了“Hello World”程序在各个祖先语言中演化过程。然后,对以 数组、字符串和切片为代表的基础结构,对以函数、方法和接 口所体现的面向过程和鸭子对象的编程,以及Go语言特有的 并发编程模型和错误处理哲学做了简单介绍。最后,针对 macOS、Windows、Linux几个主流的开发平台,推荐了几个 较友好的Go语言编辑器和集成开发环境,因为好的工具可以 极大地提高我们的效率。 1.1 Go语言创世纪
Go语言最初由Google公司的Robert Griesemer、Ken Thompson 和Rob Pike三个大牛于2007年开始设计发明,设计新语言的最 初的洪荒之力来自于对超级复杂的C++11特性的吹捧报告的鄙 视,最终的目标是设计网络和多核时代的C语言。到2008年中 期,语言的大部分特性设计已经完成,并开始着手实现编译器 和运行时,大约在这一年Russ Cox作为主力开发者加入。到了 2010年,Go语言已经逐步趋于稳定,并在9月正式发布Go语言 并开源了代码。 Go语言很多时候被描述为“类C语言”,或者是“21世纪的C语 言”。从各种角度看,Go语言确实是从C语言继承了相似的表 达式语法、控制流结构、基础数据类型、调用参数传值、指针 等诸多编程思想,还有彻底继承和发扬了C语言简单直接的暴 力编程哲学等。图1-1是《Go语言圣经》中给出的Go语言的基 因图谱,我们可以从中看到有哪些编程语言对Go语言产生了 影响。
图 1.1-1 Go语言基因族谱 首先看基因图谱的左边一支。可以明确看出Go语言的并发特 性是由贝尔实验室的Hoare于1978年发布的CSP理论演化而 来。其后,CSP并发模型在Squeak/NewSqueak和Alef等编程语 言中逐步完善并走向实际应用,最终这些设计经验被消化并吸 收到了Go语言中。业界比较熟悉的Erlang编程语言的并发编程 模型也是CSP理论的另一种实现。 再看基因图谱的中间一支。中间一支主要包含了Go语言中面
向对象和包特性的演化历程。Go语言中包和接口以及面向对 象等特性则继承自Niklaus Wirth所设计的Pascal语言以及其后 所的衍生的相关编程语言。其中包的概念、包的导入和声明等 语法主要来自于Modula-2编程语言,面向对象特性所提供的方 法的声明语法等则来自于Oberon编程语言。最终Go语言演化 出了自己特有的支持鸭子面向对象模型的隐式接口等诸多特 性。 最后是基因图谱的右边一支,这是对C语言的致敬。Go语言是 对C语言最彻底的一次扬弃,不仅仅是语法和C语言有着很多 差异,最重要的是舍弃了C语言中灵活但是危险的指针运算。 而且,Go语言还重新设计了C语言中部分不太合理运算符的优 先级,并在很多细微的地方都做了必要的打磨和改变。当然, C语言中少即是多、简单直接的暴力编程哲学则被Go语言更彻 底地发扬光大了(Go语言居然只有25个关键字,sepc语言规范 还不到50页))。 Go语言其它的一些特性零散地来自于其他一些编程语言;比 如iota语法是从APL语言借鉴,词法作用域与嵌套函数等特性 来自于Scheme语言(和其他很多编程语言)。Go语言中也有 很多自己发明创新的设计。比如Go语言的切片为轻量级动态 数组提供了有效的随机存取的性能,这可能会让人联想到链表 的底层的共享机制。还有Go语言新发明的defer语句(Ken发 明)也是神来之笔。 1.1.1 来自贝尔实验室特有基因 作为Go语言标志性的并发编程特性则来自于贝尔实验室的 Tony Hoare于1978年发表鲜为外界所知的关于并发研究的基础 文献:顺序通信进程( communicating sequential processes ,缩 写为CSP)。在最初的CSP论文中,程序只是一组没有中间共 享状态的平行运行的处理过程,它们之间使用管道进行通信和
控制同步。Tony Hoare的CSP并发模型只是一个用于描述并发 性基本概念的描述语言,它并不是一个可以编写可执行程序的 通用编程语言。 CSP并发模型最经典的实际应用是来自爱立信发明的Erlang编 程语言。不过在Erlang将CSP理论作为并发编程模型的同时, 同样来自贝尔实验室的Rob Pike以及其同事也在不断尝试将 CSP并发模型引入当时的新发明的编程语言中。他们第一次尝 试引入CSP并发特性的编程语言叫Squeak(老鼠的叫声),是 一个用于提供鼠标和键盘事件处理的编程语言,在这个语言中 管道是静态创建的。然后是改进版的Newsqueak语言(新版老 鼠的叫声),新提供了类似C语言语句和表达式的语法,还有 类似Pascal语言的推导语法。Newsqueak是一个带垃圾回收的 纯函数式语言,它再次针对键盘、鼠标和窗口事件管理。但是 在Newsqueak语言中管道已经是动态创建的,管道属于第一类 值、可以保存到变量中。然后是Alef编程语言(Alef也是C语 言之父Ritchie比较喜爱的编程语言),Alef语言试图将 Newsqueak语言改造为系统编程语言,但是因为缺少垃圾回收 机制而导致并发编程很痛苦(这也是继承C语言手工管理内存 的代价)。在Aelf语言之后还有一个叫Limbo的编程语言(地 狱的意思),这是一个运行在虚拟机中的脚本语言。Limbo语 言是Go语言最接近的祖先,它和Go语言有着最接近的语法。 到设计Go语言时,Rob Pike在CSP并发编程模型的实践道路上 已经积累了几十年的经验,关于Go语言并发编程的特性完全 是信手拈来,新编程语言的到来也是水到渠成了。 图1-2展示了Go语言库早期代码库日志可以看出最直接的演化 历程(Git用 git log --before={2008-03-03} --reverse 命令查 看)。
图 1.1-2 Go语言开发日志 从早期提交日志中也可以看出,Go语言是从Ken Thompson发 明的B语言、Dennis M. Ritchie发明的C语言逐步演化过来的, 它首先是C语言家族的成员,因此很多人将Go语言称为21世纪 的C语言。 图1-3是Go语言中来自贝尔实验室特有并发编程基因的演化过 程:
图 1.1-3 Go语言并发演化历史 纵观整个贝尔实验室的编程语言的发展进程,从B语言、C语 言、Newsqueak、Alef、Limbo语言一路走来,Go语言继承了 来着贝尔实验室的半个世纪的软件设计基因,终于完成了C语 言革新的使命。纵观这几年来的发展趋势,Go语言已经成为 云计算、云存储时代最重要的基础编程语言。 1.1.2 你好, 世界 按照惯例,介绍所有编程语言的第一个程序都是“Hello, World!”。虽然本教假设读者已经了解了Go语言,但是我们还 是不想打破这个惯例(因为这个传统正是从Go语言的前辈C语 言传承而来的)。代码1-1展示的Go语言程序输出的是中文“你 好, 世界!”。 代码 1.1-1 package main import "fmt" func main() { fmt.Println( "你好, 世界!" ) } 将以上代码保存到 hello.go 文件中。因为代码中有非ASCII 的中文字符,我们需要将文件的编码显式指定为无BOM的 UTF8编码格式(源文件采用UTF8编码是Go语言规范所要求 的)。然后进入命令行并切换到 hello.go 文件所在的目录。
目前我们可以将Go语言当作脚本语言,在命令行中直接输入 go run hello.go 来运行程序。如果一切正常的话。应该可以 在命令行看到输出"你好, 世界!"的结果。 现在,让我们简单介绍一下程序。所有的Go程序,都是由最 基本的函数和变量构成,函数和变量被组织到一个个单独的 Go源文件中,这些源文件再按照作者的意图组织成合适的 package,最终这些package再有机地组成一个完整的Go语言程 序。其中,函数用于包含一系列的语句(指明要执行的操作序 列),以及执行操作时存放数据的变量。我们这个程序中函数 的名字是main。虽然Go语言中,函数的名字没有太多的限 制,但是main包中的main函数默认是每一个可执行程序的入 口。而package则用于包装和组织相关的函数、变量和常量。 在使用一个package之前,我们需要使用import语句导入包。例 如,我们这个程序中导入了fmt包(fmt是format单词的缩写, 表示格式化相关的包),然后我们才可以使用fmt包中的Println 函数。 而双引号包含的“你好, 世界!”则是Go语言的字符串面值常量。 和C语言中的字符串不同,Go语言中的字符串内容是不可变更 的。在以字符串作为参数传递给fmt.Println函数时,字符串的 内容并没有被复制——传递的仅仅是字符串的地址和长度(字 符串的结构在 reflect.StringHeader 中定义)。在Go语言中, 函数参数都是以复制的方式(不支持以引用的方式)传递(比较 特殊的是,Go语言闭包函数对外部变量是以引用的方式使 用)。 1.2 Hello, World 的革命 在创世纪章节中我们简单介绍了Go语言的演化基因族谱,对 其中来自于贝尔实验室的特有并发编程基因做了重点介绍,最 后引出了Go语言版的“Hello, World”程序。其实“Hello,
World”程序是展示各种语言特性的最好的例子,是通向该语言 的一个窗口。这一节我们将沿着各个编程语言演化的时间轴, 简单回顾下“Hello, World”程序是如何逐步演化到目前的Go语 言形式、最终完成它的革命使命的。 图 1.2-1 Go语言并发演化历史 1.2.1 B语言 - Ken Thompson, 1972 首先是B语言,B语言是Go语言之父贝尔实验室的Ken Thompson早年间开发的一种通用的程序设计语言,设计目的 是为了用于辅助UNIX系统的开发。但是因为B语言缺乏灵活 的类型系统导致使用比较困难。后来,Ken Thompson的同事 Dennis Ritchie以B语言为基础开发出了C语言,C语言提供了丰 富的类型,极大地增加了语言的表达能力。到目前为止它依然 是世界上最常用的程序语言之一。而B语言自从被它取代之 后,则就只存在于各种文献之中,成为了历史。 目前见到的B语言版本的“Hello World”,一般认为是来自于 Brian W. Kernighan编写的B语言入门教程(Go核心代码库中的 第一个提交者名字正是Brian W. Kernighan),程序如下: 代码 1.2-1 main() { extrn a, b, c; putchar(a); putchar(b); putchar(c);
putchar('!*n'); } a 'hell'; b 'o, w'; c 'orld'; 由于B语言缺乏灵活的数据类型,只能分别以 a/b/c 全局变 量来定义要输出的内容,并且每个变量的长度必须对齐到了4 个字节(有一种写汇编语言的感觉)。然后通过多次调用 putchar 函数输出字符,最后的 '!*n' 表示输出一个换行的 意思。 总体来说,B语言简单,功能也比较简陋。 1.2.2 C语言 - Dennis Ritchie, 1974 ~ 1989 C语言是由Dennis Ritchie在B语言的基础上改进而来,它增加 了丰富的数据类型,并最终实现了用它重写UNIX的伟大目 标。C语言可以说是现代IT行业最重要的软件基石,目前主流 的操作系统几乎全部是由C语言开发的,许多基础系统软件也 是C语言开发的。C系家族的编程语言占据统治地位达几十年 之久,半个多世纪以来依然充满活力。 在Brian W. Kernighan于1974年左右编写的C语言入门教程中, 出现了第一个C语言版本的“Hello World”程序。这给后来大部 分编程语言教程都以“Hello World”为第一个程序提供了惯例。 第一个C语言版本的“Hello World”程序如下: 代码 1.2-2
main() { printf ( "hello, world" ); } 关于这个程序,有几点需要说明的:首先是 main 函数因为 没有明确返回值类型,默认返回 int 类型;其次 printf 函 数默认不需要导入函数声明即可以使用;最后 main 没有明 确返回语句,但默认返回0值。在这个程序出现时,C语言还 远未标准化,我们看到的是上古时代的C语言语法:函数不用 写返回值,函数参数也可以忽略,使用printf时不需要包含头 文件等。 这个例子同样出现在了1978年出版的《C程序设计语言》第一 版中,作者正是Brian W. Kernighan 和 Dennis M. Ritchie(简称 K&R)。书中的“Hello World”末尾增加了一个换行输出: 代码 1.2-3 main() { printf ( "hello, world\n" ); } 这个例子在字符串末尾增加了一个换行,C语言的 \n 换行比 B语言的 '!*n' 换行看起来要简洁了一些。 在K&R的教程面世10年之后的1988年,《C程序设计语言》第 二版终于出版了。此时ANSI C语言的标准化草案已经初步完 成,但正式版本的文档尚未发布。不过书中的“Hello World”程
序根据新的规范增加了 #include <stdio.h> 头文件包含语句, 用于包含 printf 函数的声明(新的C89标准中,仅仅是针对 printf 函数而言,依然可以不用声明函数而直接使用)。 代码 1.2-4 #include <stdio.h> main() { printf ( "hello, world\n" ); } 然后到了1989年,ANSI C语言第一个国际标准发布,一般被 称为C89。C89是流行最广泛的一个C语言标准,目前依然被大 量使用。《C程序设计语言》第二版的也再次印刷新版本,并 针对新发布的C89规范建议,给 main 函数的参数增加了 void 输入参数说明,表示没有输入参数的意思。 代码 1.2-5 #include <stdio.h> main( void ) { printf ( "hello, world\n" ); } 至此,C语言本身的进化基本完成。后面的C92/C99/C11都只
The above is a preview of the first 20 pages. Register to read the complete e-book.