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

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語言的自動垃圾收集器對編寫正確的代碼是一個巨大的幫助,但也並非說你徹底不用考慮內存了。你雖然不須要顯式地分配和釋放內存,可是要編寫高效的程序你依然須要瞭解變量的生命週期。例如,若是將指向短生命週期對象的指針保存到具備長生命週期的對象中,特別是保存到全局變量時,會阻止對短生命週期對象的垃圾回收(從而可能影響程序的性能)。優化

相關文章
相關標籤/搜索