Nocopy 最小的例子?

Nocopy minimal example?

我一直在尝试让 noCopy 指令为我自己的结构之一工作,但我无法让 go vet 检测到它。

我可以用它来检测 sync.WaitGroupsync.Mutex 的复制,但不能检测我自己的结构。兽医来源中的 This test file 甚至不会触发我的 go vet

或者,它发现了一些错误:

# command-line-arguments
./govet.go:56:6: no new variables on left side of :=
./govet.go:110:17: unsafe.Sizeof(mu) evaluated but not used
./govet.go:111:18: unsafe.Sizeof(mu) evaluated but not used
./govet.go:112:10: unsafe.Sizeof(mu) evaluated but not used

但是复制锁检测没有发现任何东西。

this discussion 1.4 以来 go vet 有什么变化吗?我是 运行 go version go1.11 darwin/amd64.

首先,go vet 正确检测到复制锁。示例:

type My struct {
    l sync.Mutex
}

用法:

func main() {
    m := My{}
    m2 := m
    fmt.Println(m2)
}

运行go vet,输出为:

./play.go:25: assignment copies lock value to m2: main.My contains sync.Mutex
./play.go:26: call of fmt.Println copies lock value: main.My contains sync.Mutex

所以这两种情况(分配和传递给 fmt.Println())都被检测到了。

这也意味着让您的结构在复制时成为 vet 目标的最简单方法,只需添加一个 sync.Mutex 类型的字段。这是一个现成的解决方案,尽管它会消耗内存(sync.Mutex 不是零大小结构)。是否使用这个互斥量并不重要(我们在上面的例子中没有使用它)。

在您引用的讨论中,Rob Pike 建议创建一个类型:

type noCopy struct{}
func (*noCopy) Lock() {}

并使用这种类型的字段(常规或嵌入式)来标记不可复制的结构(如果发生这种情况,让 go vet 尖叫)。

我不知道这是否有效,但目前无效,因为 go vet 检查 sync.Locker 接口,它也有一个 Unlock() 方法:

type Locker interface {
        Lock()
        Unlock()
}

因此,如果我们创建一个实现 sync.LockernoCopy 类型(更准确地说是它的指针类型),那将起作用:

type noCopy struct{}

func (*noCopy) Lock()   {}
func (*noCopy) Unlock() {}

type By struct {
    noCopy noCopy
}

正在测试:

func main() {
    b := By{}
    b2 := b
    fmt.Println(b2)
}

运行 go vet:

./play.go:29: assignment copies lock value to b2: main.By contains main.noCopy
./play.go:30: call of fmt.Println copies lock value: main.By contains main.noCopy

以下是与 go vetnoCopy 相关的一些更改:

Go 1.7

Go 1.8