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