Nocopy最小示例?

时间:2018-09-25 09:08:29

标签: go struct mutex

我一直在尝试获取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

1 个答案:

答案 0 :(得分:2)

首先,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())。

这也意味着在复制时使结构成为兽医目标的最简单方法是,只需添加类型sync.Mutex的字段。尽管它消耗内存(sync.Mutex不是零大小的结构),但这是一个现成的解决方案。不管是否使用此互斥锁都没有关系(在上面的示例中我们没有使用它)。

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

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

并使用此类型的字段(常规字段或嵌入式字段)将结构标记为不可复制(因此,在发生这种情况时发出go vet尖叫)。

我不知道这种方法是否曾经奏效,但目前还没有奏效,因为go vet检查sync.Locker接口,该接口也具有Unlock()方法:

type Locker interface {
        Lock()
        Unlock()
}

因此,如果我们创建实现noCopy的{​​{1}}类型(更确切地说是其指针类型),它将起作用:

sync.Locker

测试:

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 vet相关的一些更改:

Go 1.7

Go 1.8