我们在Go项目中,经常使用defer来完成日志管理、打点等辅助功能,非常nice,但是有个坑需要注意:
1、关于闭包:
defer方法原理是编译时先将defer内容堆栈,然后在方法return之前,弹栈并依次执行。因此defer闭包和显示调用会有参数差异。
例如:
func Test(t *testing.T) {
i := 1
defer logs.Error("i=%d", i)
i = 2
return
}
这里defer在编译时,直接将logs.Error("i=%d", 1)堆进栈,然后在return前执行,结果是"i=1"
而:
func Test(t *testing.T) {
i := 1
defer func() {
logs.Error("i=%d", i)
}()
i = 2
return
}
这里defer编译时只将闭包func扔进栈,所以在return前再调用时,临时拿到外部方法的参数最终值i=2,因此结果是"i=2"。
失了个智