• 《Go 语言设计与实现》

  • 价格:免费
  • 状态:全书已完结
  • 在读人数:14
  • 热度:615
创建者
内容简介
历史和现状 
Go 语言是诞生于 2009 年的编程语言,发展到今天已经有过去了 10 多年1。目前的 Go 语言在国内外的社区都非常热门,很多著名的开源框架,例如:Kubernetes、etcd 和 Prometheus 等都使用 Go 语言开发,近年来热门的微服务架构和云原生技术也为 Go 语言社区带来了非常多的活力。

作者目前也使用 Go 语言作为日常开发的主要语言,虽然 Go 语言没有 Lisp 系语言的开发效率和强大表达能力,但是却是一门非常容易使用并且大规模运用的工程语言,这也是作者学习和使用 Go 语言的主要原因。

作者是从 2018 年才开始学习和使用 Go 语言的,刚刚接触 Go 语言时是有些排斥和拒绝的,一度认为 Go 语言 GOPATH 的设计非常诡异,而简单的语法也导致了低下的表达能力并且影响开发效率。但是随着对 Go 语言的深入学习和理解,作者的这一观念也在不断改变。

到了今天,作者认为我们在工业界需要这么一门语法简单的编译型语言,它能够提供简单的抽象和概念,虽然目前 Go 语言也有很多问题,但是语言以及周边工具的不断完善也让作者感受到了社区的活力,也坚定地认为这门语言未来的发展会越来愈好。

为什么要写这本书 
目前的市面上分析 Go 语言实现的书籍较少,多数的书籍都偏重于 Go 语言基础和实战。虽然目前有很多分析 Go 语言的博客,但是它们却都面临以下的两个问题:
1.大量博客会成段的展示源代码的实现细节,没有提供较好的可读性;
2.少部分博客的质量较高,它们对 Go 语言的一些模块讲解的比较深入,但是不够系统,不能形成足够丰富、完整的内容;
除了上述的这些原因之外,目前关心 Go 语言设计以及演进的博客和书籍比较罕见,然而理解 Go 语言的发展史是帮助我们深入理解语言的有效途径,我们不应该忽视这一过程。

写作理念 
分析语言设计与实现的书籍不是特别的好写,很多文章都会陷入对不重要的细节,大量的篇幅都是复制的源代码,分析介绍的过程也没有分清主次,不能提供很好的阅读体验。本书会遵循以下的一些理念为读者提供高质量的内容:

通过大量配图帮助读者理解实现细节;
通过历史的演进和社区讨论理解设计背后的决策和原因;
删减源代码中的无关细节并给出精准到行的源码链接;
提供切实可行的源码阅读方法;
作者会通过以上的不同手段帮助各位读者理解 Go 语言的设计以及实现原理。

目标读者 
本书不建议没有任何编程经验的读者阅读,其目标读者包含以下几部分人群:

学习过 Go 语言并且想要理解背后设计与实现的开发者;
有过其他语言的开发经验,想要学习 Go 语言的开发者;
章节目录
  • 第一章 准备工作
  • 1.1 调试源代码
  • Go 语言作为开源项目,我们可以很轻松地获取它的源代码,它有着非常复杂的项目结构和庞大的代码库,今天的 Go 语言中差不多有 150 万行源代码,其中包含将近 140 万行的 Go 语言代码,我们可以使用如下所示的命令查看项目中代码的行数: $ cloc src5988 text files.5875 unique fil
  • 第二章 编译原理
  • 2.1 编译过程
  • Go 语言是一门需要编译才能运行的编程语言,也就是说代码在运行之前需要通过编译器生成二进制机器码,包含二进制机器码的文件才能在目标机器上运行,如果我们想要了解 Go 语言的实现原理,理解它的编译过程就是一
  • 2.2 词法分析和语法分析
  • 当使用通用编程语言1进行编写代码时,我们一定要认识到代码首先是写给人看的,只是恰好可以被机器编译和执行,而很难被人理解和维护的代码是非常糟糕。代码其实是按照约定格式编写的字符串,经过训练的软件工程师能对本来无意义的字符串进行分组和分析,按照约
  • 2.3 类型检查
  • 我们在上一节中介绍了 Go 语言编译的第一个阶段 — 通过词法和语法分析器的解析得到了抽象语法树,本节会继续介绍编译器执行的下一个阶段 — 类型检查。提到类型检查和编程语言的类型系统,很多朋友可能会想到几个有些模糊并且不好理解的术语:强类型、弱类型、静态类型和动态类型。但是我们既然要谈到 Go 语言编译器的类型检查过程,我们接下来就彻底搞清楚这几个『类型
  • 2.4 中间代码生成
  • 前两节介绍的词法与语法分析以及类型检查两个部分都属于编译器前端,它们负责对源代码进行分析并检查其中存在的词法和语法错误,经过这两个阶段生成的抽象语法树已经不存在语法错误了,本节将继续介绍编译器的后端工作 —— 中间代码生成。2.4.1 概述 中间代码是编译器或者虚拟机使用
  • 2.5 机器码生成
  • Go 语言编译的最后一个阶段是根据 SSA 中间代码生成机器码,这里谈的机器码是在目标 CPU 架构上能够运行的二进制代码,中间代码生成一节简单介绍的从抽象语法树到 SSA 中间代码的生成过程,将近 50 个生成中间代码
  • 第三章 数据结构
  • 3.1 数组
  • 数组和切片是 Go 语言中常见的数据结构,很多刚刚使用 Go 的开发者往往会混淆这两个概念。数组作为最常见的集合在编程语言中是非常重要的,除了数组之外,Go 语言引入了另一个概念 — 切片,切片与数组有一些类似,但是它们的不同导致了使用上的巨大差别。我们在这一节中会从 Go 语言的编译期间
  • 3.2 切片
  • 上一节介绍的数组在 Go 语言中没那么常用,更常用的数据结构是切片,即动态数组,其长度并不固定,我们可以向切片中追加元素,它会在容量不足时自动扩容。在 Go 语言中,切片类型的声明方式与数组有一些相似,不过由于切片的长度是动态的,所以声明时只需要指定切片中的元素类型: []int []interface{} 从切片的定义我们能推测出,切片在编译期间的生成的类型只会包含切
  • 3.3 哈希表
  • 本节会介绍 Go 语言的哈希的实现原理,哈希是除了数组之外,最常见的数据结构。几乎所有的语言都会有数组和哈希表两种集合元素,有的语言将数组实现成列表,而有的语言将哈希称作字典或者映射。无论如何命名或者如何实现,数组和哈希是两种设计集合元素的思路,数组用于表示元素的序列,而哈希表示的是键值对之间映射关系。哈希表1是一种古老的数据结构,在 195
  • 3.4 字符串
  • 字符串是 Go 语言中的基础数据类型,虽然字符串往往被看做一个整体,但是它实际上是一片连续的内存空间,我们也可以将它理解成一个由字符组成的数组,本节会详细介绍字符串的实现原理、转换过程以及常见操作的实现。字符串
  • 第四章 语言基础
  • 4.1 函数调用
  • 函数是 Go 语言的一等公民,掌握和理解函数的调用过程是我们深入学习 Go 无法跳过的,本节将从函数的调用惯例和参数传递方法两个方面分别介绍函数的执行过程。4.1.1 调用惯例 无论是系统级编程语言 C 和 Go,还是脚本语言 Ruby 和 Python,这些编程语言在调用函数时往往
  • 4.2 接口
  • Go 语言中的接口是一组方法的签名,它是 Go 语言的重要组成部分。使用接口能够让我们写出易于测试的代码,然而很多工程师对 Go 的接口了解都非常有限,也不清楚其底层的实现原理,这成为了开发高性能服务的阻碍。本节会介绍使用接口时遇到的一些常见问题以及它的设计与实现,包括接口的类型转换、类型断言以及动态派发机制,帮助各位读者更好地理
  • 4.3 反射
  • 虽然在大多数的应用和服务中并不常见,但是很多框架都依赖 Go 语言的反射机制简化代码。因为 Go 语言的语法元素很少、设计简单,所以它没有特别强的表达能力,但是 Go 语言的 reflect 包能够弥补它在语法上reflect.Type的一些劣势。reflect 实现了运行
  • 第五章 常用关键字
  • 5.1 for 和 range
  • 循环是所有编程语言都有的控制结构,除了使用经典的三段式循环之外,Go 语言还引入了另一个关键字 range 帮助我们快速遍历数组、切片、哈希表以及 Channel 等集合类型。本节将深入分析 Go 语言的两种循环,也就是 for 循环和 for-range 循环,我们会分析这两种循
  • 5.2 select
  • select 是操作系统中的系统调用,我们经常会使用 select、poll 和 epoll 等函数构建 I/O 多路复用模型提升程序的性能。Go 语言的 select 与操作系统中的 select 比较相似,本节会介绍 Go 语言 select 关键字常见的现象、数据结构以及实现原理。C 语言的 sele
  • 5.3 defer
  • 很多现代的编程语言中都有 defer 关键字,Go 语言的 defer 会在当前函数返回前执行传入的函数,它会经常被用于关闭文件描述符、关闭数据库连接以及解锁资源。这一节会深入 Go 语言的源代码介绍 defer 关键字的实现原理,相信读者读完这一节会对 defer 的数据结
  • 5.4 panic 和 recover
  • 本节将分析 Go 语言中两个经常成对出现的两个关键字 — panic 和 recover。这两个关键字与上一节提到的 defer 有紧密的联系,它们都是 Go 语言中的内置函数,也提供了互补的功能。图 5-12 panic 触发的递归延迟调用panic 能够改变程序的控制流,调用 panic 后会立刻停止执行当前函数的剩余代码
  • 5.5 make 和 new
  • 当我们想要在 Go 语言中初始化一个结构时,可能会用到两个不同的关键字 — make 和 new。因为它们的功能相似,所以初学者可能会对这两个关键字的作用感到困惑1,但是它们两者能够初始化的变量却有较大的不同。 1.make 的作用是初始化
  • 第六章 并发编程
  • 6.1 上下文 Context
  • 上下文 context.Context Go 语言中用来设置截止日期、同步信号,传递请求相关值的结构体。上下文与 Goroutine 有比较密切的关系,是 Go 语言中独特的设计,在其他编程语言中我们很少见到类似的概念。context.Context 是 Go 语言在 1.7 版本中引入标准库的接口1,该接口定义了
  • 6.2 同步原语与锁
  • Go 语言作为一个原生支持用户态进程(Goroutine)的语言,当提到并发编程、多线程编程时,往往都离不开锁这一概念。锁是一种并发编程中的同步原语(Synchronization Primitives),它能保证多个 Goroutine 在访问同一片内存时不会出现竞争条件(Race conditi
  • 6.3 计时器
  • 准确的时间对于任何一个正在运行的应用非常重要,但是在分布式系统中我们很难保证各个节点的绝对时间一致,哪怕通过 NTP 这种标准的对时协议也只能把各个节点上时间的误差控制在毫秒级,所以准确的相对时间在分布式系统中显得更为重要,本节会分析用于
  • 6.4 Channel
  • 作为 Go 核心的数据结构和 Goroutine 之间的通信方式,Channel 是支撑 Go 语言高性能并发编程模型的重要结构本节会介绍管道 Channel 的设计原理、数据结构和常见操作,例如 Channel 的创建、发送、接收和关闭。虽然 Channel 与关
  • 6.5 调度器
  • Go 语言在并发编程方面有强大的能力,这离不开语言层面对并发编程的支持。本节会介绍 Go 语言运行时调度器的实现原理,其中包含调度器的设计与实现原理、演变过程以及与运行时调度相关的数据结构。谈到 Go 语言调度器,我们绕不开的是操作系统、进程与线程这些概念,线程是操作系统
  • 6.6 网络轮询器
  • 在今天,大部分的服务都是 I/O 密集型的,应用程序会花费大量时间等待 I/O 操作的完成。网络轮询器是 Go 语言运行时用来处理 I/O 操作的关键组件,它使用了操作系统提供的 I/O 多路复用机制增强程序的并发处理能力。本节会深入分析 Go 语言网络轮询器的设计与实现原理。6.6.1 设计原理 网络轮询器不仅用于监控网络 I/O,还能用于监控文件的 I/O,它利用了操
  • 6.7 系统监控
  • 很多系统中都有守护进程,它们能够在后台监控系统的运行状态,在出现意外情况时及时响应。系统监控是 Go 语言运行时的重要组成部分,它会每隔一段时间检查 Go 语言运行时,确保程序没有进入异常状态。本节会介绍 Go 语言系统监控的设计与实现原理,包括它的启动、执行过程以及主要职责。6.7.1 设计原理 在支持多任
  • 第七章 内存管理
  • 7.1 内存分配器
  • 程序中的数据和变量都会被分配到程序所在的虚拟内存中,内存空间包含两个重要区域:栈区(Stack)和堆区(Heap)。函数调用的参数、返回值以及局部变量大都会被分配到栈上,这部分内存会由编译器进行管理;不同编程语言使用不同的方法管理堆区的内存,C++ 等编程语言会由工程师主动申请和释放内存,Go 以及 Java 等编程语言会由工程师和编译器共同管理,堆中的对象由内存分配器分配并由垃圾收集器回收。
  • 7.2 垃圾收集器
  • 熟悉 Go 语言的开发者一般都非常了解 Goroutine 和 Channel 的原理,包括如何设计基于 CSP 模型的应用程序,但是 Go 语言的插件系统是很少有人了解的模块,通过插件系统,我们可以在运行时加载动态库实现一些比较有趣的功能。8.1.1 设计原理 Go 语言的插件系统基于 C 语言动态库实现的,所以它也继承了
  • 7.3 栈空间管理
  • 应用程序的内存一般会分成堆区和栈区,程序在运行期间可以主动从堆区申请内存空间,这些内存由内存分配器分配并由垃圾收集器负责回收,我们在上两节已经详细分析了堆内存的申请和释放过程,本节会介绍 Go 语言栈内存的管理。7.3.1 设计原理
  • 第八章 元编程
  • 8.1 插件系统
  • 熟悉 Go 语言的开发者一般都非常了解 Goroutine 和 Channel 的原理,包括如何设计基于 CSP 模型的应用程序,但是 Go 语言的插件系统是很少有人了解的模块,通过插件系统,我们可以在运行时加载动态库实现一些比较
  • 8.2 代码生成
  • 图灵完备可能是很多工程师经常听说的术语,它的一个重要特性是计算机程序可以生成另一个程序1,本届要介绍的就是 Go 语言的代码生成机制。很多人可能认为生成代码在软件中并不常见,但是实际上它在很多场景中都扮演了重要的角色,Go 语言中的测试就使用了代码生成机制,go te
  • 第九章 标准库
  • 9.1 JSON
  • JSON(JavaScript 对象表示,JavaScript Object Notation)作为一种轻量级的数据交换格式1,在今天几乎占据了绝大多数的市场份额。虽然与更紧凑的数据交换格式相比,它的序列化和反序列化性能不足,但是 JSON 提供了良好的可读性与易用性,在不追求极致机制性能的情况下,使用 JSON 作为序列化格式是一种非常好的选择。9.1.1 设计原理 几乎所有的现
  • 9.2 HTTP
  • 超文本传输协议(Hypertext Transfer Protocol、HTTP 协议)是今天使用最广泛的应用层协议,1989 年由 Tim Berners-Lee 在 CERN 起草的协议已经成为了互联网的数据传输的核心1。在过去几年的时间里,HTT
  • 9.3 数据库
  • 数据库几乎是所有 Web 服务不可或缺的一部分,在所有类型的数据库中,关系型数据库是我们在想要持久存储数据时的首要选择。因为关系型数据库的种类繁多,所以 Go 语言的标准库 database/sql 仅为访问关系
  • 第十章 完结篇
  • 10.1 附录1
  • 《Go 语言设计与实现》纸质书预售了!有 500 本签名版,不想听「图书出版背后那些事儿」而要直接下单的读者朋友可以直接扫描下面的二维码购买。这里将主要从封面设计方案、图书与博客的区别、图书折扣、签名版几个方面,简单跟大家介绍一下。封面设计方案 在《Go 语言设计与实现》纸质书诚邀读者评论这篇文章之后,本来是想请大家看纸质书的封面设计方案的,但是因为怕造成太多打扰,最终没有发文章邀请读者讨论
  • 10.2 附录2
  • 感谢诸位 大家都知道,纸质书是基于我的开源电子书《Go 语言设计与实现》,是我深入学习 Go 的过程中对这门语言底层设计与实现原理的全部心得与体会。不少读者见证了电子书的诞生,期间大家一起学习,一起讨论。回复大家的问题一方面帮助我个人精进了 Go 语言知识,另一方面还纠正了内容中的不少细节问题。借着纸质书出版的机会,在此感谢大家。此外,感谢谢孟军、毛剑、万
读者评论
  • 你还没登录,点击这里
  • 本书评论
最近这些人在读这本书