go语言的局部变量在堆上还是栈上?

在讨论之前,先看如下代码:

 1 type treeNode struct {
 2     value int
 3     left, right *treeNode
 4 }
 5 
 6 func createNode(value int) *treeNode {
 7     return &treeNode{value:value}
 8 }
 9 
10 func main() {
11     root := createNode(10)
12     fmt.Println(root)
13 }

上面这段代码createNode函数返回了一个局部变量的地址给main函数中的root,但是fmt.Println正常打印出来了新建的node的内容。这要是在C++中这么写,是个很典型的错误:返回局部变量的地址,该地址的内容在函数退出后会被自动释放,因为是在栈上的。

那么go语言的局部变量到底是在栈上还是堆上呢?go语言编译器会做逃逸分析(escape analysis),分析局部变量的作用域是否逃出函数的作用域,要是没有,那么就放在栈上;要是变量的作用域超出了函数的作用域,那么就自动放在堆上。所以不用担心会不会memory leak,因为go语言有强大的垃圾回收机制。这样可以释放程序员的内存使用限制,让程序员关注程序逻辑本身。

 

对于new出来的局部变量,也不是一定就放在堆上,而是根据其是否超出了函数作用域来判断是否放在堆上还是栈上。这点和C语言很不一样。

posted @ 2018-08-04 11:04  guhowo  阅读(2274)  评论(0编辑  收藏  举报