go vet
强烈建议在go开发中使用go vet
对代码做一下初步检查。
1 |
|
此命令对代码进行静态检查,对fmt格式化, mutex死锁或者一些因拷贝之类的问题导致锁无效,死代码等问题上报可疑问题。
有以下代码:
type Foo struct {
i int
locker sync.Mutex
}
func (o *Foo) Update(v int) {
fmt.Printf("pointer receiver object address: %p\n", o)
o.locker.Lock()
o.i = v
o.locker.Unlock()
}
func (o Foo) Print() {
fmt.Printf("value receiver object address: %p\n", &o)
o.locker.Lock()
fmt.Println("value is: ", o.i)
o.locker.Unlock()
}
func main() {
foo := Foo{
i: 10,
locker: sync.Mutex{},
}
foo.Update(100)
foo.Print()
foo.Update(200)
foo.Print()
}
执行结果:
1 |
|
go vet
提示:
1 |
|
原因出在value receiver
和pointer receiver
:
在go中这两种类型的method是这样的:
- value receiver: 调用此种方法时,每次调用都将复制一个新的对象来调用此对象的方法。
- pointer receiver: 调用此种方法时,每次调用都将传递的是引用,指向的是同一个对象。
如果想要在方法调用时改变绑定对象的变量,应该采用pointer receiver
这种方式。
对于go vet
的可疑报告。在同一个Foo实例上调用Update和Print时,锁将失效。因为Print方法与Update方法操作的是两个不同实例。