存在某些情況,GoLang 中某些不應複製的結構體。例如,有時全域組態應該只有一個版本在整個應用程式中傳遞,而不應被複製和修改。
在 GoLang 中,沒有直觀的解決方案來防止結構體的複製。但仍然有一些方法可以利用來幫助防止在開發程式碼時發生這種情況。技巧是定義一些實現sync.Locker
介面的結構體,並將此結構體嵌入任何不應複製的結構體中。
// noCopy 可嵌入到不應在第一次使用後複製的結構體中。
//
// 詳細資訊請參閱 https://golang.org/issues/8005#issuecomment-190753527
// 。
type noCopy struct{}
// Lock 是 `go vet` 的 -copylocks 檢查器使用的無操作函式。
func (*noCopy) Lock() {}
func (*noCopy) UnLock() {}
下面是一個解釋上述內容的程式碼片段。
package main
import (
"fmt"
)
type noCopy struct{}
func (*noCopy) Lock() {}
func (*noCopy) Unlock() {}
type Demo struct {
noCopy noCopy
}
func Copy(d Demo) {
}
func main() {
d := Demo{}
fmt.Printf("%+v", d)
Copy(d)
fmt.Printf("%+v", d)
}
現在,如果您在 main.go 檔案上執行go vet
,您將看到一些錯誤,告訴您某些地方複製了結構體 (Copy()
)。
> go vet main.go
# command-line-arguments
.\main.go:16: Copy 傳遞鎖定值:main.Demo 包含 main.noCopy
.\main.go:21: fmt.Printf 的呼叫複製鎖定值:main.Demo 包含 main.noCopy
.\main.go:23: Copy 的呼叫複製鎖定值:main.Demo 包含 main.noCopy
.\main.go:25: fmt.Printf 的呼叫複製鎖定值:main.Demo 包含 main.noCopy
需要注意的是,上述方法不會讓編譯器編譯失敗。如果您繼續編譯和執行它,它仍然可以工作。這只為go vet
提供了另一個提示,我們通常在構建專案之前執行它,以檢查我們的原始碼中可能存在潛在問題。
> go run main.go
{noCopy:{}}{noCopy:{}}
參考: