当前位置:  首页>> 技术小册>> GO面试指南

Go 的 GC(垃圾回收)演变经历了几个版本的迭代和优化。下面简要介绍一下 Go 中 GC 的演变历程。

Go 1.0
在 Go 1.0 中,采用的是标记-清除(mark-and-sweep)算法进行垃圾回收。这种算法的主要特点是将内存分为已分配的和未分配的两部分,其中已分配的内存称为“堆”,未分配的内存称为“栈”。垃圾回收器通过标记堆中的存活对象,并清除未标记的对象来回收内存。

下面是一个使用 Go 1.0 版本进行垃圾回收的示例代码:

  1. package main
  2. func main() {
  3. // 分配一个 1MB 的切片
  4. data := make([]byte, 1<<20)
  5. // 释放内存
  6. data = nil
  7. // 强制进行垃圾回收
  8. runtime.GC()
  9. }

在这个示例代码中,我们首先使用 make 函数分配了一个 1MB 大小的切片,然后将其赋值为 nil,即释放了内存。最后,我们使用 runtime.GC() 函数强制进行垃圾回收。

Go 1.5
在 Go 1.5 中,采用了并发标记-清除(concurrent mark-and-sweep)算法进行垃圾回收。这种算法的主要特点是在程序运行期间,垃圾回收器会在程序运行的同时进行标记和清除操作,从而避免了程序暂停的时间。

下面是一个使用 Go 1.5 版本进行垃圾回收的示例代码:

  1. package main
  2. import "time"
  3. func main() {
  4. // 分配一个 1MB 的切片
  5. data := make([]byte, 1<<20)
  6. // 释放内存
  7. data = nil
  8. // 等待 1 秒钟
  9. time.Sleep(time.Second)
  10. }

在这个示例代码中,我们首先使用 make 函数分配了一个 1MB 大小的切片,然后将其赋值为 nil,即释放了内存。最后,我们使用 time.Sleep 函数等待了 1 秒钟,这个过程中垃圾回收器会在后台进行并发的标记和清除操作。

Go 1.8
在 Go 1.8 中,采用了并发标记-整理(concurrent mark-and-sweep with compaction)算法进行垃圾回收。这种算法的主要特点是在进行标记和清除操作的同时,还会将存活对象移动到一起,从而使得堆中的内存连续,减少了内存碎片的产生。

下面是一个使用 Go 1.8 版本进行垃圾回收的示例代码:

  1. package main
  2. import (
  3. "fmt"
  4. "runtime"
  5. )
  6. func main() {
  7. var m runtime.MemStats
  8. // 获取垃圾回收器统计信息
  9. runtime.ReadMemStats(&m)
  10. fmt.Printf("Alloc = %v MiB\n", m.Alloc/1024/1024)
  11. fmt.Printf("TotalAlloc = %v MiB\n", m.TotalAlloc/1024/1024)
  12. fmt.Printf("Sys = %v MiB\n", m.Sys/1024/1024)
  13. fmt.Printf("NumGC = %v\n", m.NumGC)
  14. }

在这个示例代码中,我们首先使用 runtime.MemStats 结构体来存储垃圾回收器的统计信息。

然后,我们使用 runtime.ReadMemStats 函数获取垃圾回收器的统计信息,并输出了分配的内存大小、总分配的内存大小、系统分配的内存大小和垃圾回收次数。


该分类下的相关小册推荐: