我写了下面的代码。我知道返回在函数中创建的变量的地址是错误的方法,因为创建的局部变量将位于堆栈中,并且在完成函数后该变量将从堆栈中弹出。我创建了一个名为“latif”的人。然后我使用了changeName()函数。它将 person 结构的名称字段更改为“uluman”。它返回了局部变量的地址。函数完成后,局部变量应该被弹出。然后我调用了 sum() 函数来保证堆栈将发生变化(sum 函数的参数将被推送。换句话说,内存中的单元格值 x 点应该发生变化)。所以 x 指向堆栈中的某个位置。package main import "fmt" type Person struct{ name string age int } func sum(a, b int)int{ return a+b } func (t Person ) changeName(value string)*Person{ t.name = value return &t //Delibiratly the address of the local variable is returned } func main(){ t := Person{name : "latif" } fmt.Println("Before" , t.name) x := t.changeName("uluman") _= sum(5,10) fmt.Println("After" , x.name) return }我预计fmt.Println(x.name)应该打印与“uluman”不同的内容,因为 x 指向堆栈地址并且它已经更改,但它打印了“uluman”。这里有什么问题吗?
1 回答
泛舟湖上清波郎朗
TA贡献1818条经验 获得超3个赞
这被称为“逃逸分析”。
Go编译器尝试找出变量的地址是否“转义”了函数,如果是,它会在堆而不是堆栈中分配该变量。在这种情况下,它发现 的地址t逃逸了changeName函数,因此它被分配在堆中,而不是堆栈中。这就是你的程序有效的原因。
例如,这是构造结构的常见方法:
type X struct {
...
}
func NewX() *X {
a:=X{}
...
return &a
}
这里,a是在堆中分配的,而不是在堆栈上,因为编译器知道它a会转义函数。
以下内容也有效:
func f() {
i:=0
go func() {
...
i++
...
}()
}
上面,i转义了f,因为地址i位于新创建的 goroutine 的闭包中。f回国后继i续生活。
- 1 回答
- 0 关注
- 115 浏览
添加回答
举报
0/150
提交
取消