Go 開發(fā)者不需要寫代碼來釋放程序中不再使用的變量和結(jié)構(gòu)占用的內(nèi)存,在 Go 運行時中有一個獨立的進(jìn)程,即垃圾收集器(GC),會處理這些事情,它搜索不再使用的變量然后釋放它們的內(nèi)存??梢酝ㄟ^ runtime 包訪問 GC 進(jìn)程。
通過調(diào)用 runtime.GC() 函數(shù)可以顯式的觸發(fā) GC,但這只在某些罕見的場景下才有用,比如當(dāng)內(nèi)存資源不足時調(diào)用 runtime.GC(),它會在此函數(shù)執(zhí)行的點上立即釋放一大片內(nèi)存,此時程序可能會有短時的性能下降(因為 GC 進(jìn)程在執(zhí)行)。
如果想知道當(dāng)前的內(nèi)存狀態(tài),可以使用:
// fmt.Printf("%d\n", runtime.MemStats.Alloc/1024)
// 此處代碼在 Go 1.5.1下不再有效,更正為
var m runtime.MemStats
runtime.ReadMemStats(&m)
fmt.Printf("%d Kb\n", m.Alloc / 1024)
上面的程序會給出已分配內(nèi)存的總量,單位是 Kb。進(jìn)一步的測量參考 文檔頁面。
如果需要在一個對象 obj 被從內(nèi)存移除前執(zhí)行一些特殊操作,比如寫到日志文件中,可以通過如下方式調(diào)用函數(shù)來實現(xiàn):
runtime.SetFinalizer(obj, func(obj *typeObj))
func(obj *typeObj) 需要一個 typeObj 類型的指針參數(shù) obj,特殊操作會在它上面執(zhí)行。func 也可以是一個匿名函數(shù)。
在對象被 GC 進(jìn)程選中并從內(nèi)存中移除以前,SetFinalizer 都不會執(zhí)行,即使程序正常結(jié)束或者發(fā)生錯誤。
練習(xí) 10.17
從練習(xí) 10.16 開始(它基于結(jié)構(gòu)體實現(xiàn)了一個棧結(jié)構(gòu)),為棧的實現(xiàn)(stack_struct.go)創(chuàng)建一個單獨的包 stack,并從 main 包 main.stack.go 中調(diào)用它。