我一直在尝试获取noCopy
指令以用于我自己的结构之一,但是我无法获取go vet
来检测它。
我可以检测到sync.WaitGroup
和sync.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
。
答案 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
相关的一些更改: