菜单

Go 概述

相关源文件

本文档介绍了 Go 编程语言、其仓库结构以及构成 Go 编程生态系统的主要组件。它涵盖了 Go 实现的关键架构元素,包括运行时系统、编译器、构建系统和标准库。

有关使用 Go 开发应用程序的具体详细信息,请参阅 语言规范和文档

Go 简介

Go 是一种静态类型、编译型编程语言,由 Google 的 Robert Griesemer、Rob Pike 和 Ken Thompson 设计。它旨在实现简单、高效,并通过 goroutine 和 channel 内置对并发编程的支持。Go 将编译型语言的性能和类型安全性与动态语言的易用性和开发人员生产力相结合。

Go 的主要特点包括:

  • 垃圾回收
  • 具有类型推断的强静态类型
  • 并发原语(goroutines 和 channels)
  • 快速编译
  • 功能丰富的标准库
  • 跨平台支持

Go 的实现由多个相互关联的系统组成,如下图所示:

来源:src/runtime/proc.go22-32 doc/go_spec.html9-25 src/cmd/go/alldocs.go8-34

存储库结构

Go 仓库的组织结构如下:

目录目的
src/包含 Go 编程语言、运行时、编译器和标准库的源代码。
src/runtime/Go 运行时实现(垃圾收集器、调度器等)
src/cmd/go/Go 命令行工具的实现
src/cmd/compile/Go 编译器实现
src/cmd/link/Go 链接器实现
doc/文档,包括语言规范。
test/Go 实现的测试文件。
src/internal/用于实现目的的内部包。

Go 的实现遵循了各种系统之间清晰的划分,它们之间有明确定义的接口。

来源:src/runtime/proc.go1-20 src/cmd/go/alldocs.go1-7

Go 运行时系统

运行时系统是 Go 执行环境的核心。它实现了 goroutine 调度、内存管理、垃圾收集以及支持 Go 程序所需的其他低级功能等基本特性。

Goroutine 调度器

Go 调度器负责将 goroutine(轻量级线程)分发到可用的操作系统线程上。它实现了一个基于 G-P-M 模型的高级协作调度系统:

  • G (Goroutine):代表一个 goroutine,这是一个轻量级的用户空间线程。
  • M (Machine):代表一个执行 Go 代码的操作系统线程。
  • P (Processor):代表执行 Go 代码所需的资源,本质上是一个调度器上下文。

调度器使用工作窃取算法来保持所有 CPU 的忙碌。当一个 goroutine 阻塞时(例如,在 I/O 或 channel 操作上),运行时系统会从其 P 中分离 M,并调度另一个 goroutine 来运行。

来源:src/runtime/proc.go22-114 src/runtime/runtime2.go35-107 src/runtime/proc.go147-330

内存管理

Go 使用自定义的内存分配器和垃圾收集器来自动管理内存。关键组件包括:

  1. 分配器:处理 Go 对象的内存分配,使用大小类来最小化碎片。
  2. :动态分配的对象存储的主要内存区域。
  3. :管理局部变量和函数调用的地方。

内存系统有几个层级:

  • 小对象分配使用快速的、特定于大小的分配器。
  • 中到大对象的分配由中央堆处理。
  • 非常大的分配可能直接从操作系统映射。

来源:src/runtime/malloc.go5-76 src/runtime/mheap.go56-63 src/runtime/mbitmap.go5-17

垃圾回收

Go 实现了一个并发的、三色标记清除垃圾收集器。它与应用程序并发运行,以最大限度地减少暂停时间。

垃圾收集过程有几个阶段:

  1. 标记阶段:通过从根节点跟踪来识别所有可达的对象。
  2. 标记终止:完成标记并准备清除。
  3. 清除阶段:回收不可达对象的内存。

垃圾收集器使用写屏障来跟踪在并发标记阶段修改的指针,确保不会遗漏任何对象。它还实现了比例调度,以确保 GC 工作分布在一段时间内。

来源:src/runtime/mgc.go5-118 src/runtime/mgcmark.go5-16 src/runtime/mgcsweep.go1-10 src/runtime/mgcpacer.go14-16

Go 编译器

Go 编译器将 Go 源代码转换为机器码。它包含几个阶段:

  1. 前端(解析和类型检查):将 Go 源代码解析为抽象语法树 (AST) 并执行类型检查。
  2. 中间件(中间表示):将 AST 转换为中间表示以进行优化。
  3. 后端(代码生成):为目标平台生成机器码。

Go 编译器旨在快速编译。它避免了复杂的、会减慢编译速度的优化,但仍然能生成相当高效的代码。

来源:src/cmd/go/internal/work/gc.go34-46

构建系统

Go 构建系统由 go 命令实现,负责编译和链接 Go 程序。 go build 命令将包和依赖项编译成可执行二进制文件。

构建过程包括几个步骤

  1. 包加载:解析并加载包依赖项。
  2. 编译:将每个包编译成目标文件。
  3. 链接:将目标文件链接成可执行文件。

构建系统使用动作图来表示构建步骤之间的依赖关系。它可以并行构建多个包,并缓存构建结果以加快后续构建速度。

来源: src/cmd/go/internal/work/exec.go1-6 src/cmd/go/internal/work/build.go1-3 src/cmd/go/internal/work/exec.go72-238

包管理

Go 的构建系统包含包管理,现在主要通过 Go 模块来处理。模块是版本化的相关 Go 包的集合,由 go.mod 文件定义。

go 命令处理模块操作,例如

  • 使用 go get 解析和下载依赖项
  • 管理模块缓存
  • 维护版本兼容性

来源: src/cmd/go/alldocs.go669-710

标准库

Go 提供了一个全面的标准库,无需外部依赖即可提供基本功能。标准库组织成包,每个包专注于特定领域,如 I/O、网络、编码等。

标准库中的关键包包括

描述
fmt格式化 I/O,函数类似于 C 的 printf 和 scanf
io基本 I/O 接口
net/httpHTTP 客户端和服务器实现
encoding/jsonJSON 编码和解码
os操作系统功能
sync同步原语
time与时间相关的函数

标准库的设计强调简洁性、可组合性和一致性。

来源: src/cmd/go/internal/load/pkg.go57-146 src/runtime/time.go5-6

测试框架

Go 内置了一个测试框架,位于 testing 包中。测试是写在文件名以 _test.go 结尾的文件中的函数。 go test 命令可以自动化运行测试。

测试框架支持

  • 单元测试,使用 func TestXxx(*testing.T)
  • 基准测试,使用 func BenchmarkXxx(*testing.B)
  • 示例,使用 func ExampleXxx()
  • 模糊测试,使用 func FuzzXxx(*testing.F)

go test 命令处理测试发现、执行和报告。它还可以生成代码覆盖率报告并并行运行测试。

来源: src/cmd/go/internal/test/test.go52-177 src/cmd/go/internal/load/test.go1-3

工具链

Go 工具链包含多个支持 Go 开发的命令行工具

工具描述
go build编译包和依赖项
go run编译并运行 Go 程序
go test测试包
go get将依赖项添加到当前模块并安装它们
go mod模块维护
go fmt格式化 Go 源代码
go vet报告包中可能存在的错误
go doc显示包或符号的文档

所有这些工具都集成到 go 命令中,它为 Go 工具链提供了统一的接口。

来源: src/cmd/go/alldocs.go14-34 src/cmd/go/internal/envcmd/env.go5-8 src/cmd/go/internal/help/helpdoc.go33-53

总结

Go 的架构围绕协同工作的关键系统构建:运行时系统负责执行和内存管理,编译器将 Go 代码翻译成机器码,构建系统协调编译和链接,标准库提供基本功能。这种模块化设计使 Go 能够实现其简洁、高效和高生产力的目标。

有关特定组件的更详细信息,请参阅本手册的其他页面。