Golang中逃逸现象-变量何时 栈何时堆

变量的逃逸现象

  • 将⼀个局部变量的地址返回给上层函数,依然能够访问,那么这个局部变量产⽣的了逃逸现象,当前变量应该并没有分配到栈上。
package main

//inline内联函数
func foo(arg_val int) *int {
	var foo_val1 int = 11
	var foo_val2 int = 12
	var foo_val3 int = 13
	var foo_val4 int = 14
	var foo_val5 int = 15

	//目的是防止编译器优化,优化成内联函数,而不产生foo函数的调用函数
	for i := 0; i < 5; i++ {
		//为了辨别每个变量的地址是否在栈上还是堆上
		println(&arg_val, &foo_val1, &foo_val2, &foo_val3, &foo_val4, &foo_val5)
	}

	//返回foo_val3的地址给main函数
	return foo_val3
}

func main() {

	main_val := foo(666)

	println(*main_val, main_val)
}

注意:以上函数在C++是编译不通过的,因为C++函数返回后,栈已经清空,这个时候,指针指向一个不存在的领域,则编译不通过

通过Golang编译器分析逃逸现象

Golang中逃逸现象-变量何时 栈何时堆_第1张图片

  • go tool compile -m demo2.go

      通过提示得知哪些变量是被逃逸的
    
  • 编译汇编⽂件
    Golang中逃逸现象-变量何时 栈何时堆_第2张图片
    发现foo_val3确实是通过runtime.newobject来开辟,是在堆上,不是栈上,确实发⽣逃逸

new出来的变量是在“栈”还是“堆”?

  • golang中的new,创建⼀个空间,未必是在堆上开辟的
    结论:Golang中⼀个函数局部变量,不管是不是动态new出来的,还是普通定义出来的,分配到堆上还是栈上,开发者决定不了。⽽是通过编译器做逃逸分析来决定的。

Golang中 new 和 make的区别?

  • 相同之处

      给变量分配空间的
    
  • 不同之处

      make 只是⽤slice、channel、map初始化,⽆可替代
      new ⽤于类型的内存分配(初始化是0),不常⽤, 原因 通过“:=”来初始化⽐较常⽤
    

你可能感兴趣的:(Go)