Go 將會支持弱指針 weak!你知道嗎?
大家好,我是煎魚。
最近 Go 又有了新的動作,一路綠燈,已經(jīng)審批通過了新增弱指針(weak pointers)庫的提案,這對于 Go 來講是一個不錯的補充。
今天這篇文章我們主要分享弱指針的介紹,讓大家有一個基本前瞻。因為這個提案已經(jīng) Accepted!
弱指針是什么
此處是引用 Go 官方提案給出的介紹和原因,也就是為什么 Go 核心團隊認(rèn)可要去做弱指針。
弱指針(或其他語言中的弱引用)允許開發(fā)人員引用內(nèi)存,而不妨礙垃圾回收器回收內(nèi)存。為防止出現(xiàn)可見的懸掛引用,弱指針在引用的內(nèi)存被回收時會變?yōu)榱恪?/p>
弱指針可以轉(zhuǎn)換為常規(guī)(“強”)指針,這樣就能防止垃圾回收器回收內(nèi)存,并允許對內(nèi)存進行典型使用和訪問。
弱指針通常比普通指針更難處理,因為它們隨時都可能變?yōu)榱?。幾乎每一次弱指針到強指針的轉(zhuǎn)換都必須進行 nil 檢查。通常,弱指針會在意想不到的時候變?yōu)榱恪?/p>
盡管如此,弱指針仍然存在于許多語言中,因為它們非常有用。弱指針的主要使用場景與高效內(nèi)存管理和回收有關(guān)。
可能的場景包含但不限于:
- 為規(guī)范化映射有效管理內(nèi)存,或為生命周期與另一個對象的生命周期綁定的內(nèi)存(類似于 JavaScript 的 WeakMap)有效管理內(nèi)存。
- 弱指針的另一個良好用例是向 GC 提示:可以放棄某些資源,因為以后重建這些資源的成本很低,尤其是在這些資源占用大量內(nèi)存的情況下。
弱指針 API 設(shè)計
Go 官方計劃新增一個 weak 包,添加以下 API 作為弱指針的使用:
type Pointer[T any] struct { ... }
func Make[T any](ptr *T "T any") Pointer[T] { ... }
func (p Pointer[T]) Value() *T { ... }
這些 API 主要用于創(chuàng)建和管理弱指針。Pointer[T] 是一個弱指針類型,能夠引用類型為 T 的值,但不會阻止該值被垃圾回收。
使用 Make 函數(shù)可以從一個有效的指針中創(chuàng)建一個弱指針,而 Value 方法則返回原始指針,若值已被回收則返回 nil。
弱指針的比較遵循特定規(guī)則,例如:同一對象的不同字段創(chuàng)建的弱指針不相等,且如果對象通過 runtime.SetFinalizer 復(fù)活,之前的弱指針也會失效。
這樣的設(shè)計目的是為了有效管理內(nèi)存并避免內(nèi)存泄漏。
使用例子
前 Go 核心團隊負責(zé)人 rsc 在接納這個提案時,設(shè)計了一個弱緩存抽象的例子。
代碼如下:
type Cache[K any, V any] struct {
f func(*K) V
m atomic.Map[weak.Pointer[K], func() V]
}
func NewCache[K comparable, V any](f func(*K "K comparable, V any")V) *Cache[K, V] {
return &Cache[K, V]{f: f}
}
func (c *Cache[K, V]) Get(k *K) V {
kw := weak.Make(k)
vf, ok := c.m.Load(kw)
if ok {
return vf()
}
vf = sync.OnceValue(func() V { return c.f(k) })
vf, loaded := c.m.LoadOrStore(kw)
if !loaded {
// Stored kw→vf to c.m; add the cleanup.
runtime.AddCleanup(k, c.cleanup, kw)
}
return vf()
}
func (c *Cache[K, V]) cleanup(kw weak.Pointer[K]) {
c.m.Delete(kw)
}
var cached = NewCache(expensiveComputation)
部分社區(qū)爭議
爭議主要集中在以下幾個方面:
- 必要性:部分開發(fā)者質(zhì)疑弱指針是否解決了實際問題,是否足夠常用。
- 復(fù)雜性:有人擔(dān)心引入弱指針會增加代碼復(fù)雜性,尤其對新手開發(fā)者。
- 性能開銷:討論弱指針可能帶來的性能影響,是否值得引入。
- 兼容性:考慮弱指針與現(xiàn)有內(nèi)存管理機制的兼容性。
- 接口設(shè)計:對弱指針的具體實現(xiàn)和接口設(shè)計存在不同意見。
總的來講,圍繞著弱指針的實際需求、使用復(fù)雜性及其對性能的影響。還有如何設(shè)計其接口等問題展開。
注:問題都是問題。rsc 已經(jīng)以一己之力把這個提案往 Accepted 推了。
總結(jié)
后續(xù)弱指針的引用,可以給 Go 的使用打開一個新的 “后門”。隨著這個趨勢的不斷形成,個人覺得以后 Go 也能有一派開發(fā)者針對自己的高性能要求的代碼場景玩出一波騷操作了。