我寫了下面的代碼。我知道返回在函數(shù)中創(chuàng)建的變量的地址是錯誤的方法,因為創(chuàng)建的局部變量將位于堆棧中,并且在完成函數(shù)后該變量將從堆棧中彈出。我創(chuàng)建了一個名為“l(fā)atif”的人。然后我使用了changeName()函數(shù)。它將 person 結(jié)構(gòu)的名稱字段更改為“uluman”。它返回了局部變量的地址。函數(shù)完成后,局部變量應(yīng)該被彈出。然后我調(diào)用了 sum() 函數(shù)來保證堆棧將發(fā)生變化(sum 函數(shù)的參數(shù)將被推送。換句話說,內(nèi)存中的單元格值 x 點應(yīng)該發(fā)生變化)。所以 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 }我預(yù)計fmt.Println(x.name)應(yīng)該打印與“uluman”不同的內(nèi)容,因為 x 指向堆棧地址并且它已經(jīng)更改,但它打印了“uluman”。這里有什么問題嗎?
1 回答

泛舟湖上清波郎朗
TA貢獻(xiàn)1818條經(jīng)驗 獲得超3個贊
這被稱為“逃逸分析”。
Go編譯器嘗試找出變量的地址是否“轉(zhuǎn)義”了函數(shù),如果是,它會在堆而不是堆棧中分配該變量。在這種情況下,它發(fā)現(xiàn) 的地址t逃逸了changeName函數(shù),因此它被分配在堆中,而不是堆棧中。這就是你的程序有效的原因。
例如,這是構(gòu)造結(jié)構(gòu)的常見方法:
type X struct {
...
}
func NewX() *X {
a:=X{}
...
return &a
}
這里,a是在堆中分配的,而不是在堆棧上,因為編譯器知道它a會轉(zhuǎn)義函數(shù)。
以下內(nèi)容也有效:
func f() {
i:=0
go func() {
...
i++
...
}()
}
上面,i轉(zhuǎn)義了f,因為地址i位于新創(chuàng)建的 goroutine 的閉包中。f回國后繼i續(xù)生活。
- 1 回答
- 0 關(guān)注
- 149 瀏覽
添加回答
舉報
0/150
提交
取消