在Go語言中,變數的生命週期指的是程式運行期間變數有效存在的時間間隔。全域變數的生命週期和整個程式的運行週期是一致的;局部變數的生命週期則是動態的,從創建這個變數的宣告語句開始,到這個變數不再被引用為止。
本教學操作環境:windows7系統、GO 1.18版本、Dell G3電腦。
Go語言變數的生命週期
#變數的生命週期指的是程式執行期間變數有效存在的時間間隔。
變數的生命週期與變數的作用域有著不可分割的連結:
#全域變數:它的生命週期和整個程式的運作週期是一致的;
局部變數:它的生命週期則是動態的,從創建這個變數的宣告語句開始,到這個變數不再被引用為止;
形式參數和函數傳回值:它們都屬於局部變量,在函數被呼叫的時候創建,函數呼叫結束後被銷毀。
for t := 0.0; t < cycles*2*math.Pi; t += res { x := math.Sin(t) y := math.Sin(t*freq + phase) img.SetColorIndex( size+int(x*size+0.5), size+int(y*size+0.5), blackIndex, // 最后插入的逗号不会导致编译错误,这是Go编译器的一个特性 ) // 小括号另起一行缩进,和大括号的风格保存一致 }
上面程式碼中,在每次循環的開始都會建立臨時變數 t,然後在每次循環迭代中建立臨時變數 x 和 y。臨時變數 x、y 存放在堆疊中,隨著函數執行結束(執行遇到最後一個}),釋放其記憶體。
堆疊和堆疊的差異在於:
#堆(heap):堆是用來存放在執行過程中被動態分配的記憶體段。它的大小並不固定,可動態擴張或縮減。當進程呼叫 malloc 等函數分配記憶體時,新分配的記憶體會被動態加入到堆上(堆被擴張)。當利用free 等函數釋放記憶體時,被釋放的記憶體從堆中被剔除(堆被縮減);
#堆疊(stack):堆疊又稱堆疊, 用來存放程式暫時創建的局部變量,也就是我們函數的大括號{ }定義的局部變數。
在程式的編譯階段,編譯器會根據實際情況自動選擇在堆疊或堆疊上分配局部變數的儲存空間,無論使用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(垃圾回收機制)回收這個變數的內存空間。
在實際的開發中,並不需要刻意的實現變數的逃逸行為,因為逃逸的變數需要額外分配內存,同時對效能的最佳化可能會產生細微的影響。
雖然Go語言能夠幫助我們完成對記憶體的分配和釋放,但是為了能夠開發出高效能的應用我們任然需要了解變數的宣告週期。例如,如果將局部變數賦值給全域變量,將會阻止 GC 對這個局部變數的回收,導致不必要的記憶體佔用,進而影響程式的效能。
以上是Go語言變數的生命週期是啥的詳細內容。更多資訊請關注PHP中文網其他相關文章!