pointers - 局部变量的返回地址产生意外值

标签 pointers go stack

我写了下面的代码。我知道返回一个变量的地址是
在函数中创建是错误的方法,因为创建的局部变量将在堆栈中,并且
完成函数后,变量将从堆栈中弹出。
我创建了一个名为“latif”的人。然后,我使用了changeName()函数。它将人员结构的名称字段更改为“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'。
这是怎么了

最佳答案

这称为“逃逸分析”。

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继续生效。

关于pointers - 局部变量的返回地址产生意外值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58961986/

相关文章:

javascript - 从功能声明的堆栈访问变量

c - c 中带有指针的 fread 和 fwrite

c - 指针矩阵在代码中间被取消引用

c - 释放指向其他结构的结构中的指针

go - 对于上下文而言,取消如此强制吗?

api - GO单元测试结构化REST API项目

json - 使用单个表绑定(bind)数组/结构中的多个列

c - 运行时检查失败 #2-变量 x2 周围的堆栈已损坏

c - 指针递增和解引用(需要左值错误)

assembly - 在 x86 NASM 汇编语言中离开函数时,堆栈是否会自动弹出?