在 Go 中,defer 语句可以用来在函数退出前执行一些必要的清理工作,比如关闭文件或者释放锁等操作。在 defer 语句中,如果使用了函数参数,那么在 defer 语句执行时,会对参数进行取值并将其压入栈中。但需要注意的是,由于 defer 的实现方式,如果在 defer 语句执行时变量已经被修改,那么 defer 执行时获取的变量值可能和预期不一致。
下面是一个示例代码,演示了 defer 的变量快照失效的情况:
package main
import (
"fmt"
)
func main() {
x := 1
defer func() {
fmt.Println("defer x =", x)
}()
x++
fmt.Println("x =", x)
}
输出结果为:
x = 2
defer x = 1
可以看到,在 defer 语句中,变量 x 的值被快照为 1,而不是预期的 2。这是因为在 defer 语句执行时,x 的值已经被修改,所以获取到的值是之前的值。
要避免这种情况,可以将变量复制一份,在 defer 语句中使用复制后的变量。例如:
package main
import (
"fmt"
)
func main() {
x := 1
y := x
defer func() {
fmt.Println("defer x =", y)
}()
x++
fmt.Println("x =", x)
}
输出结果为:
x = 2
defer x = 1
可以看到,在 defer 语句中,使用了复制后的变量 y,所以获取到的值为 1,与预期一致。