1. 程式人生 > >go 臨時物件池sync.Pool

go 臨時物件池sync.Pool

sync.Pool是go標準庫中的同步工具,可被稱為臨時物件池。屬於結構體型別,值在使用之後,就不應該再被複制。

臨時物件:不需要持久使用的某一類值,這類值對程式來說,可有可無。建立和銷燬可有在任何時候發生,完全不影響程式功能。

可以使用臨時物件池當作某種資料的快取。

sync.Pool只有兩個方法:

put:在當前的臨時物件池中存放臨時物件

get:從當前的臨時物件池中獲取臨時物件。先從臨時物件池刪除值,再把這個值返回。如果當前池中沒有任何值,這個方法會返回當前臨時物件池的New欄位建立一個新值,並直接將其返回。

sync.Pool的New欄位代表建立臨時物件函式。如果get方法到了最後也沒有任何值返回,就會呼叫該New函式。該函式的結果並不會存入當前的臨時物件池,而是直接返回給get方法的呼叫者。

 

New欄位的實際值需要我們在初始化臨時物件池的時候給定,否則在呼叫get的時候會返回nil。

為什麼說臨時物件池中的值會被及時清理掉?

因為go執行時系統的gc,所有每次開始執行之前,都會對所有已建立的臨時物件池中的值進行全面清除

sync包在被初始化的時候,會向go語言執行時系統註冊一個函式,這個函式的功能就是清除所有已建立的臨時物件池中的值。可以成為池清理函式,一旦池清理函式被註冊到了go語言執行時系統。執行時系統在每次即將執行垃圾回收的時候就會執行池清理函式。

在sync包中還存在一個包級私有的全域性變數,這個變數代表了當前程式中使用的所有臨時物件池的彙總,是元素型別為*sync.Pool的切片,可以稱為池彙總表。

在臨時物件池的put或者get第一次被呼叫的時候,這個池就會被新增到池彙總列表。正因為如此,池清理函式總是能訪問到所有正在被真正使用的臨時物件池。

更確切的說,池清理函式會遍歷池彙總列表,對其中的每一個臨時物件池,都會先將池中所有的私有臨時物件和共享臨時物件列表都置為nil,然後再把這個池中的所有池列表都銷燬。

最後,池清理函式會把池彙總列表置為空的切片。這樣,這些池中儲存的臨時物件就被全部清除了。如果臨時物件池以外的程式碼再無對他們的引用,那麼在稍後的gc中,就會被銷燬,佔用的記憶體空間也會被回收。