Golang 怎麼實現禁止拷貝
一、前言
禁止拷貝即是用戶無法對對象進行拷貝,比如源碼包中的 sync.waitgroup,就是不可以拷貝的。
二、如何實現禁止複製
查看 sync 包下的源碼得知看一下 go 的源碼如何實現禁止拷貝的,如下:
type noCopy struct{}
// Lock is a no-op used by -copylocks checker from `go vet`.
func (*noCopy) Lock() {}
func (*noCopy) Unlock() {}
noCopy 是一個 golang 基礎包內部的結構體(小寫開頭,說明不對外暴露,不想讓用戶調用)。
當我們聲明的結構體裏包含 noCopy 時:
package main
import (
"fmt"
)
type noCopy struct{}
// Lock is a no-op used by -copylocks checker from `go vet`.
func (*noCopy) Lock() {}
func (*noCopy) Unlock() {}
type DoNotCopyMe struct {
noCopy
}
func main() {
var d DoNotCopyMe
d2 := d // 這裏發生了拷貝
fmt.Println(d2)
}
直接運行的話,可以正常輸出:
> go run .\main.go
{{}}
只有執行 go vet 檢查纔可以發現問題,如下:
> go vet .\main.go
# command-line-arguments
.\main.go:20:8: assignment copies lock value to d2: command-line-arguments.DoNotCopyMe
.\main.go:21:14: call of fmt.Println copies lock value: command-line-arguments.DoNotCopyMe
如果錯誤的使用不能被 copy 的代碼審覈,運行命令時不會看到輸出。
從上面的實驗我們可以得出兩點結論:
-
如果一個結構體實現了 Lock 和 Unlock 函數,原則上就不能被拷貝。
-
但是編譯器沒有做限制,如果想知道代碼裏是否有錯誤的用法,需要用 go vet 命令檢查。
三、實現案例
package main
import (
"fmt"
)
type noText struct{}
func (*noText) Lock() {}
func (*noText) Unlock() {}
type Demo struct {
noCopy noText
}
func Copy(d Demo) {
CopyTwice(d)
}
func CopyTwice(d Demo) {}
func main() {
d := Demo{}
fmt.Printf("%+v", d)
Copy(d)
fmt.Printf("%+v", d)
}
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/VRSgFRdEjrz1KMz5JMwGvA