为了账号安全,请及时绑定邮箱和手机立即绑定

指针 (GoLang)

指针 (GoLang)

Go
叮当猫咪 2022-10-10 18:06:50
这是一个菜鸟问题,请多多包涵。所以问题是为什么 f() 函数指向不同的地址。我的理解是变量 v 必须覆盖旧值。package mainimport "fmt"var p = f()func f() *int {    v := 1    return &v}func main() {    fmt.Println(f())    fmt.Println(f())    fmt.Println(f())    fmt.Println(p)}//0xc0000140b0//0xc0000140b8//0xc0000140e0//0xc000014098
查看完整描述

2 回答

?
catspeake

TA贡献1111条经验 获得超0个赞

编译器检测到v escapes该函数f,因此将其分配在堆上。每次调用f都会返回 的新实例v,这就是每次调用都会看到不同地址的原因。



查看完整回答
反对 回复 2022-10-10
?
翻过高山走不出你

TA贡献1875条经验 获得超3个赞

给这个简单的答案


Go 查找比当前堆栈帧寿命更长的变量,然后堆分配它们


基本上,变量 v 转义了函数 f 堆栈帧并在堆中分配,这就是为什么您每次都会看到不同的地址打印的原因。


阅读这篇关于逃逸分析的精彩介绍。https://medium.com/a-journey-with-go/go-introduction-to-the-escape-analysis-f7610174e890


尝试运行逃逸分析以查看所有逃逸的变量。


go build -gcflags="-m" main.go:

./main.go:7:2: moved to heap: v   //points to v := 1

./main.go:12:15: moved to heap: v //points to fmt.Println(f())

./main.go:13:15: moved to heap: v //points to fmt.Println(f())

./main.go:14:15: moved to heap: v //points to fmt.Println(f())

请注意,最后一条fmt.Println(f())语句不考虑转义,因为传递给 Println 的值p是全局变量,因此它已经在堆中,因此不需要escape.


查看完整回答
反对 回复 2022-10-10
  • 2 回答
  • 0 关注
  • 114 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号