Golang 中你應該知道的 noCopy 策略

在 Go 開發中,我們經常遇到 noCopy 這種結構體,並伴隨一個常見的註釋 "must not be copied after first use"。本文將深入探討 noCopy 的作用,以及 Go Vet 如何幫助我們避免潛在的錯誤。

sync.noCopy 的作用

sync.noCopy 結構體通常與 sync.WaitGroup 等同步原語一起出現,例如:

type WaitGroup struct {
    noCopy noCopy

    state atomic.Uint64 // high 32 bits are counter, low 32 bits are waiter count.
    sema  uint32
}

noCopy 結構體本身是一個空結構體,它實現了 LockUnlock 方法,這兩個方法都是空操作。它沒有實際的功能屬性,但它的存在卻意義重大。

Go Vet 和 "Locks Erroneously Passed by Value"

Go Vet 是 Go 語言自帶的代碼檢查工具,它可以幫助我們發現潛在的代碼錯誤。copylocks 是 Go Vet 的一個檢查器,它會檢查代碼中是否錯誤地通過值傳遞了包含鎖的結構體。

例如:

func func1(wg sync.WaitGroup) {
    wg.Add(1)
    // ...
    wg.Done()
}

func func2() {
    var wg sync.WaitGroup
    func1(wg)
    wg.Wait() // 這裏會造成錯誤
}

func2 中,我們通過值傳遞了 wg,導致 func1 中的 wg 成了一個新的副本。當 func1 中的 wg 執行 Done() 操作時,func2 中的 wg 仍然是 Add(1) 的狀態,最終導致 wg.Wait() 無法正常工作。

Go Vet 的 copylocks 檢查器會檢測到這種錯誤,並提示我們 "Locks Erroneously Passed by Value"。

noCopy 的作用機制

noCopy 結構體通過與 Go Vet 的 copylocks 檢查器配合,來阻止開發者錯誤地通過值傳遞包含鎖的結構體。

當一個結構體包含 noCopy 類型時,Go Vet 會檢查該結構體是否被通過值傳遞。如果被通過值傳遞,Go Vet 會發出警告,提醒開發者該結構體不應該被複制。

使用 noCopy 的其他場景

除了同步原語,noCopy 還可以用於其他需要阻止複製的場景,例如:

總結

noCopy 是一種簡單的機制,但它可以有效地防止開發者錯誤地複製包含鎖或其他重要數據的結構體,從而避免潛在的錯誤。

當我們看到 noCopy 結構體時,應該意識到它的作用,並仔細檢查代碼,確保沒有錯誤地複製包含鎖或其他重要數據的結構體。

擴展知識

在 Go 語言中,還有其他一些防止複製的策略,例如:

選擇合適的策略取決於具體的應用場景和需求。

希望本文能夠幫助你更好地理解 noCopy 策略,並在 Go 語言開發中避免潛在的錯誤。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/cm9kh7KaYbMfwGNIc_vUyg?poc_token=HNMG-WajXARNrti5mNJfePWY0VsLlfzq3KMuo04-