
go 的垃圾回收由运行时(runtime)内置的原生代码实现,采用并发标记清除算法,不依赖虚拟机;gc 过程中仅短暂 stw,与 java 的分代 gc 有本质区别。
Go 是一门编译型语言,源码直接编译为机器码,生成静态链接的原生二进制可执行文件,不依赖虚拟机(如 JVM)或解释器。但这并不意味着它没有运行时系统——恰恰相反,Go 拥有一个高度集成、用 C 和汇编编写的 Go Runtime,它内置于每个 Go 程序中,负责调度 goroutine、内存管理、栈增长、网络轮询以及垃圾回收(GC)等核心功能。
那么,谁在执行垃圾回收?
答案是:Go Runtime 中的原生(native)C/汇编代码,运行在操作系统线程(OS threads)上。它不是由 Go 语言编写的 goroutine 实现,也不是用户态抽象层的一部分;而是深度嵌入 runtime 的底层系统组件。从 Go 1.1 开始,GC 已支持并行(parallel)与并发(concurrent)模式,并在 Go 1.5 后全面转向三色标记 + 并发清除的低延迟设计。这意味着:
- 标记阶段大部分与用户代码并发执行(mutator concurrent),仅需极短的 STW(Stop-The-World)暂停(通常
- 清除阶段也逐步并发化,避免内存瞬时抖动;
- GC 工作由 runtime 自动启动(基于堆增长率触发),由多个 OS 线程协同完成,而非单一线程或某个“隐藏 goroutine”。
例如,可通过以下方式观察 GC 行为:
GODEBUG=gctrace=1 ./myapp
输出类似:
gc 1 @0.021s 0%: 0.010+1.2+0.019 ms clock, 0.080+0.24/0.70/0.36+0.15 ms cpu, 4->4->2 MB, 5 MB goal, 8 P
其中 0.010+1.2+0.019 分别表示 STW 标记开始时间、并发标记时间、STW 标记结束时间(单位:毫秒)。
⚠️ 注意事项:
- GC 不可被手动强制触发(runtime.GC() 仅建议运行,不保证立即执行,且会引发一次完整 STW,应避免在性能敏感路径调用);
- Go 的 GC 是统一堆模型(unified heap),无新生代/老年代划分,也不使用压缩(compaction)或复制算法,因此不会发生内存碎片整理,但对超大堆(>100GB)的延迟控制更具挑战;
- 与 Java HotSpot 的 G1/ZGC 等相比,Go GC 更强调简单性、确定性与部署友好性,牺牲部分吞吐量换取更低的尾部延迟(P99)和更少的调优参数(主要仅需关注 GOGC)。
总结而言:Go 的垃圾回收是一套由 runtime 原生实现、深度绑定操作系统线程、以低延迟为目标的并发标记清除系统。它既不是“黑盒线程”,也不是用户可见的 goroutine,而是现代编译型语言中“自带轻量级运行时”范式的典型体现——无需 VM,却依然提供安全、自动、高效的内存管理。










