這是一個菜鳥問題,請耐心等待。所以疑問是為什么 f() 函式指向不同的地址。我的理解是變數 v 必須覆寫舊值。
package main
import "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
uj5u.com熱心網友回復:
編譯器檢測到v escapes該函式f,因此將其分配在堆上。每次呼叫都會f回傳 的一個新實體v,這就是為什么每次呼叫都會看到不同的地址。
uj5u.com熱心網友回復:
對此做一個簡單的回答
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。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/346518.html
