垃圾回收就是自动回收程序中不再使用的内存,避免内存泄漏。程序运行时分配了很多内存,比如给变量、结构体等。当某些变量或对象再也不会被使用时,垃圾回收会回收这些内存,让系统可以重新利用它。


Go 的 GC 是怎么工作的?

Go 使用一种叫 标记-清除算法 的方式进行垃圾回收,主要分为两步:

1. 标记阶段(Mark)

这个阶段的任务是 找到正在使用的内存(也叫“活跃对象”)。

2. 清除阶段(Sweep)

这个阶段的任务是 回收未使用的内存


举个例子

假设程序中有一个 map,它占用了一些内存。你删除了 map 或者不再使用它。那么这些内存就成了“垃圾”。

  1. 标记阶段

    • Go 的垃圾回收器会找到哪些内存仍然被程序使用。
    • 如果有一些内存不再被使用(比如你已经删掉的 map),它会被标记为“垃圾”。
  2. 清除阶段

    • Go 会释放这些垃圾内存,让系统可以重新使用它们。

Go 的垃圾回收有什么特点?

1. 它是并发的

2. 停顿时间很短

3. 写屏障


内存什么时候真正释放?


如何控制 GC 行为?

GOGC 参数

GOGC 是一个环境变量,用来控制垃圾回收的频率。

你可以这样设置:

GOGC=50 ./your_program

一个简单的代码例子

package main

import (
	"fmt"
	"runtime"
)

func main() {
	// 打印当前内存使用情况
	printMemStats("Start")

	// 分配大量内存
	data := make([]byte, 100*1024*1024) // 分配 100 MB
	printMemStats("After allocation")

	// 手动触发垃圾回收
	data = nil                  // 让 data 不再引用内存
	runtime.GC()               // 手动触发 GC
	printMemStats("After GC")
}

func printMemStats(stage string) {
	var m runtime.MemStats
	runtime.ReadMemStats(&m)
	fmt.Printf("%s: Alloc = %v KB, Sys = %v KB\n", stage, m.Alloc/1024, m.Sys/1024)
}

运行结果可能是:

Start: Alloc = 512 KB, Sys = 2048 KB
After allocation: Alloc = 102400 KB, Sys = 105472 KB
After GC: Alloc = 512 KB, Sys = 2048 KB

解释


总结

  1. Go 的垃圾回收是通过 标记-清除算法 实现的,分为两个阶段:
    • 标记阶段:找到所有活跃对象。
    • 清除阶段:回收不再使用的内存。
  2. 它是并发运行的,不会明显阻塞程序。
  3. 通过 GOGC 参数可以调整垃圾回收的频率。
  4. 如果内存没有被频繁使用,Go 会将部分内存还给操作系统。