登录
首页 >  Golang >  Go问答

局部变量的返回地址生成意外值

来源:stackoverflow

时间:2024-04-02 17:09:35 245浏览 收藏

本篇文章向大家介绍《局部变量的返回地址生成意外值》,主要包括,具有一定的参考价值,需要的朋友可以参考一下。

问题内容

我写了下面的代码。我知道返回一个变量的地址 在函数中创建是一种错误的方法,因为创建的局部变量将位于堆栈中,并且 完成函数后,变量将从堆栈中弹出。 我创建了一个名为“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”。 这里出了什么问题?


解决方案


这被称为“逃逸分析”。

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继续存活。

以上就是本文的全部内容了,是否有顺利帮助你解决问题?若是能给你带来学习上的帮助,请大家多多支持golang学习网!更多关于Golang的相关知识,也可关注golang学习网公众号。

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>