我寫了下面的代碼。我知道返回在函數中創建的變量的地址是錯誤的方法,因為創建的局部變量將位于堆棧中,并且在完成函數后該變量將從堆棧中彈出。我創建了一個名為“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 關注
- 162 瀏覽
添加回答
舉報
0/150
提交
取消