在golang项目开发中,使用到了defer,代码举例如下:
func sum(i string, a, b int) int { ret := a + b fmt.Println(i) return ret } func main() { a := 1 b := 2 defer sum("1", a, sum("2", a, b)) defer sum("3", a, b) }
按照期望,defer先进后出的原则,应该是先打印出最后一个defer函数的值:
3
再打印第一个defer函数的值:
2
1
但实际打印是:
2
3
1
即第一个defer函数中的sum("2", a, b)最先被执行了,而不是我们想象中的只要是属于defer函数的内容都要等待执行。
原因分析
经过资料查找和测试,可以确定:当defer被声明时,其参数就会被实时解析,
我们通过以下代码来解释这条规则:
func a() { i := 0 defer fmt.Println(i) i++ return }
运行结果是0
这是因为虽然我们在defer后面定义的是一个带变量的函数: fmt.Println(i). 但这个变量(i)在defer被声明的时候,就已经确定其值了。
这也是为什么本案例中的示例代码会先执行sum("2", a, b)了,效果是这样的:
tmp := sum("2", a, b) defer sum("1", a, tmp)
解决方案
defer声明时,确保此时其参数的正确性,不使用不确定的变量作为入参。