Go 將會支持弱指針 weak!你知道嗎?
大家好,我是煎魚。
最近 Go 又有了新的動作,一路綠燈,已經(jīng)審批通過了新增弱指針(weak pointers)庫的提案,這對于 Go 來講是一個(gè)不錯(cuò)的補(bǔ)充。
今天這篇文章我們主要分享弱指針的介紹,讓大家有一個(gè)基本前瞻。因?yàn)檫@個(gè)提案已經(jīng) Accepted!

弱指針是什么
此處是引用 Go 官方提案給出的介紹和原因,也就是為什么 Go 核心團(tuán)隊(duì)認(rèn)可要去做弱指針。
弱指針(或其他語言中的弱引用)允許開發(fā)人員引用內(nèi)存,而不妨礙垃圾回收器回收內(nèi)存。為防止出現(xiàn)可見的懸掛引用,弱指針在引用的內(nèi)存被回收時(shí)會變?yōu)榱恪?/p>
弱指針可以轉(zhuǎn)換為常規(guī)(“強(qiáng)”)指針,這樣就能防止垃圾回收器回收內(nèi)存,并允許對內(nèi)存進(jìn)行典型使用和訪問。

弱指針通常比普通指針更難處理,因?yàn)樗鼈冸S時(shí)都可能變?yōu)榱?。幾乎每一次弱指針到?qiáng)指針的轉(zhuǎn)換都必須進(jìn)行 nil 檢查。通常,弱指針會在意想不到的時(shí)候變?yōu)榱恪?/p>
盡管如此,弱指針仍然存在于許多語言中,因?yàn)樗鼈兎浅S杏?。弱指針的主要使用場景與高效內(nèi)存管理和回收有關(guān)。
可能的場景包含但不限于:
- 為規(guī)范化映射有效管理內(nèi)存,或?yàn)樯芷谂c另一個(gè)對象的生命周期綁定的內(nèi)存(類似于 JavaScript 的 WeakMap)有效管理內(nèi)存。
 - 弱指針的另一個(gè)良好用例是向 GC 提示:可以放棄某些資源,因?yàn)橐院笾亟ㄟ@些資源的成本很低,尤其是在這些資源占用大量內(nèi)存的情況下。
 
弱指針 API 設(shè)計(jì)
Go 官方計(jì)劃新增一個(gè) 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] 是一個(gè)弱指針類型,能夠引用類型為 T 的值,但不會阻止該值被垃圾回收。
使用 Make 函數(shù)可以從一個(gè)有效的指針中創(chuàng)建一個(gè)弱指針,而 Value 方法則返回原始指針,若值已被回收則返回 nil。
弱指針的比較遵循特定規(guī)則,例如:同一對象的不同字段創(chuàng)建的弱指針不相等,且如果對象通過 runtime.SetFinalizer 復(fù)活,之前的弱指針也會失效。
這樣的設(shè)計(jì)目的是為了有效管理內(nèi)存并避免內(nèi)存泄漏。
使用例子
前 Go 核心團(tuán)隊(duì)負(fù)責(zé)人 rsc 在接納這個(gè)提案時(shí),設(shè)計(jì)了一個(gè)弱緩存抽象的例子。
代碼如下:
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ū)爭議
爭議主要集中在以下幾個(gè)方面:
- 必要性:部分開發(fā)者質(zhì)疑弱指針是否解決了實(shí)際問題,是否足夠常用。
 - 復(fù)雜性:有人擔(dān)心引入弱指針會增加代碼復(fù)雜性,尤其對新手開發(fā)者。
 - 性能開銷:討論弱指針可能帶來的性能影響,是否值得引入。
 - 兼容性:考慮弱指針與現(xiàn)有內(nèi)存管理機(jī)制的兼容性。
 - 接口設(shè)計(jì):對弱指針的具體實(shí)現(xiàn)和接口設(shè)計(jì)存在不同意見。
 
總的來講,圍繞著弱指針的實(shí)際需求、使用復(fù)雜性及其對性能的影響。還有如何設(shè)計(jì)其接口等問題展開。
注:問題都是問題。rsc 已經(jīng)以一己之力把這個(gè)提案往 Accepted 推了。
總結(jié)
后續(xù)弱指針的引用,可以給 Go 的使用打開一個(gè)新的 “后門”。隨著這個(gè)趨勢的不斷形成,個(gè)人覺得以后 Go 也能有一派開發(fā)者針對自己的高性能要求的代碼場景玩出一波騷操作了。















 
 
 
















 
 
 
 