Go語言自帶垃圾回收機制(GC)。GC 透過獨立的程序執行,它會搜尋不再使用的變數,並將其釋放。需要注意的是,GC 在執行時會佔用機器資源。
GC 是自動進行的,如果要手動進行 GC,可以使用 runtime.GC() 函式,顯式的執行 GC。顯式的進行 GC 只在某些特殊的情況下才有用,比如當記憶體資源不足時呼叫 runtime.GC() ,這樣會立即釋放一大片記憶體,但是會造成程式短時間的效能下降。
finalizer(終止器)是與物件關聯的一個函式,透過 runtime.SetFinalizer 來設定,如果某個物件定義了 finalizer,當它被 GC 時候,這個 finalizer 就會被呼叫,以完成一些特定的任務,例如發訊號或者寫日誌等。
在Go語言中 SetFinalizer 函式是這樣定義的:
func SetFinalizer(x, f interface{})
引數說明如下:
引數 x 必須是一個指向透過 new 申請的物件的指標,或者透過對複合字面值取址得到的指標。
引數 f 必須是一個函式,它接受單個可以直接用 x 型別值賦值的引數,也可以有任意個被忽略的返回值。
SetFinalizer 函式可以將 x 的終止器設定為 f,當垃圾收集器發現 x 不能再直接或間接訪問時,它會清理 x 並呼叫 f(x)。
另外,x 的終止器會在 x 不能直接或間接訪問後的任意時間被呼叫執行,不保證終止器會在程式退出前執行,因此一般終止器只用於在長期執行的程式中釋放關聯到某物件的非記憶體資源。例如,當一個程式丟棄一個 os.File 物件時沒有呼叫其 Close 方法,該 os.File 物件可以使用終止器去關閉對應的作業系統檔案描述符。
終止器會按依賴順序執行:如果 A 指向 B,兩者都有終止器,且 A 和 B 沒有其它關聯,那麼只有 A 的終止器執行完成,並且 A 被釋放後,B 的終止器才可以執行。
如果 *x 的大小為 0 位元組,也不保證終止器會執行。
此外,我們也可以使用SetFinalizer(x, nil)來清理繫結到 x 上的終止器。
提示:終止器只有在物件被 GC 時,才會被執行。其他情況下,都不會被執行,即使程式正常結束或者發生錯誤。
【示例】在函式 entry() 中定義區域性變數並設定 finalizer,當函式 entry() 執行完成後,在 main 函式中手動觸發 GC,檢視 finalizer 的執行情況。
package main
import ( "log" "runtime" "time" )
type Road int
func findRoad(r *Road) {
log.Println("road:", *r) }
func entry() { var rd Road = Road(999) r := &rd
runtime.SetFinalizer(r, findRoad) }
func main() {
entry()
for i := 0; i < 10; i++ { time.Sleep(time.Second) runtime.GC() }
}
執行結果如下:
2019/11/28 15:32:16 road: 999