C++ 语言中,需要开发者自己学习如何进行内存分配,选用怎样的内存分配方式来适应不同的算法需求。比如,函数局部变量尽量使用栈,全局变量、结构体成员使用堆分配等。
Go语言将这个过程整合到了编译器中,命名为“变量逃逸分析”。通过编译器分析代码的特征和代码的生命周期,决定应该使用堆还是栈来进行内存分配。

逃逸分析

  1. package main
  2. import "fmt"
  3. // 本函数测试入口参数和返回值情况
  4. func dummy(b int) int {
  5. // 声明一个变量c并赋值
  6. var c int
  7. c = b
  8. return c
  9. }
  10. // 空函数, 什么也不做
  11. func void() {
  12. }
  13. func main() {
  14. // 声明a变量并打印
  15. var a int
  16. // 调用void()函数
  17. void()
  18. // 打印a变量的值和dummy()函数返回
  19. fmt.Println(a, dummy(0))
  20. }

go run -gcflags “-m -l” main.go

  • -gcflags 参数是编译参数
  • -m 表示进行内存分配分析,
  • -l 表示避免程序内联,也就是避免进行程序优化

运行结果

command-line-arguments

./demo-04-变量逃逸.go:28:13: … argument does not escape ./demo-04-变量逃逸.go:28:13: a escapes to heap ./demo-04-变量逃逸.go:28:22: dummy(0) escapes to heap 0 0

  • c 是整型,被复制并作为 dummy() 函数的返回值返回, c 在 dummy() 函数中分配的内存被释放
  • 不会影响 main() 中使用 dummy() 返回的值
  • 其值通过 dummy() 的返回值“逃出”了 dummy() 函数