go局部變量的存儲空間是堆還是棧?


編譯器會自動選擇在棧上還是在堆上分配局部變量的存儲空間,但可能令人驚訝的是,這個選擇並不是由用var還是new聲明變量的方式決定的。

var global *int func f() { var x int x = 1 global = &x } func g() { y := new(int) *y = 1 }


f函數里的x變量必須在堆上分配,因為它在函數退出后依然可以通過包一級的global變量找到,雖然它是在函數內部定義的;用Go語言的術語說,這個x局部變量從函數f中逃逸了。相反,當g函數返回時,變量*y將是不可達的,也就是說可以馬上被回收的。因此,*y並沒有從函數g中逃逸,編譯器可以選擇在棧上分配*y的存儲空間(譯注:也可以選擇在堆上分配,然后由Go語言的GC回收這個變量的內存空間),雖然這里用的是new方式。其實在任何時候,你並不需為了編寫正確的代碼而要考慮變量的逃逸行為,要記住的是,逃逸的變量需要額外分配內存,同時對性能的優化可能會產生細微的影響。

Go語言的自動垃圾收集器對編寫正確的代碼是一個巨大的幫助,但也並不是說你完全不用考慮內存了。你雖然不需要顯式地分配和釋放內存,但是要編寫高效的程序你依然需要了解變量的生命周期。例如,如果將指向短生命周期對象的指針保存到具有長生命周期的對象中,特別是保存到全局變量時,會阻止對短生命周期對象的垃圾回收(從而可能影響程序的性能)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM