Go語言之GO 語言變量的生命周期


GO 語言變量的生命周期

生命周期是指程序執行過程中變量存在的時間段。

包變量(全局變量)和局部變量兩種變量的生命周期。

① 包變量一直常駐在內存到程序的結束,然后被系統垃圾回收器回收。也就是說包變量的生命周期是整個程序的執行時間。
  ② 局部變量,例如一個函數中定義的變量。它有一個動態的生命周期:每次執行生命語句時創建一個新的實體,變量一直生存到它變得不可訪問(例如沒有外部指針指向它,函數退出我們沒有路徑能訪問到這個變量),這時它占用的存儲空間就會被回收。

var p *int    //全局指針變量
func f(){
    var i int
    i = 1
    p = &x    //全局指針變量指向局部變量i
}

func f(){
    p := new(int) //局部指針變量,使用new申請的空間
    *p = 1
}

i是通過var申請的局部變量,但是由於有外部指針指向訪問,我們有路徑可找到這個空間(變量能夠逃逸出函數),所以局部變量i是申請在堆空間上。而第二個程序中p指針變量雖然是使用new申請的空間,但是由於退出函數就沒有路徑可尋找到它(變量無法逃出函數),所以局部變量p是申請在棧空間上的。 

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

分析閉包:

由於在定義Test( )函數時指定了返回的類型是一個匿名函數,並且該匿名函數返回的類型是整型。所以在Test( )函數中定義了一個匿名函數,並且將整個匿名函數返回,匿名函數返回的是整型。在main( )函數中定義了一個變量f,該變量的類型是匿名函數,f( )表示調用執行匿名函數。最終執行完成后發現,實現了數字的累加。雖然Test()已經返回了,但是返回的值:func()還在全局變量中使用,三次調用 f(),因此返回值會保存在堆上,即使棧釋放了內存資源,但func()保存在堆中,數據不會釋放。

因為匿名函數(閉包),有一個很重要的特點:

它不關心這些捕獲了的變量和常量是否已經超出了作用域,所以只有閉包還在使用它,這些變量就還會存在。


免責聲明!

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



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