golang笔记2


go vet

强烈建议在go开发中使用go vet对代码做一下初步检查。

1
go vet $(go list ./...|grep -v /vendor/)

此命令对代码进行静态检查,对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
2
3
4
5
6
pointer receiver object address: 0xc420016090
value receiver object address: 0xc4200160a0
value is:  100
pointer receiver object address: 0xc420016090
value receiver object address: 0xc4200160c0
value is:  200

go vet提示:

1
main.go:20: Print passes lock by value: main.Foo contains sync.Mutex

原因出在value receiverpointer receiver:

在go中这两种类型的method是这样的:

  • value receiver: 调用此种方法时,每次调用都将复制一个新的对象来调用此对象的方法。
  • pointer receiver: 调用此种方法时,每次调用都将传递的是引用,指向的是同一个对象。

如果想要在方法调用时改变绑定对象的变量,应该采用pointer receiver这种方式。

对于go vet的可疑报告。在同一个Foo实例上调用Update和Print时,锁将失效。因为Print方法与Update方法操作的是两个不同实例。