当前位置:  首页>> 技术小册>> GO面试指南

在 Go 中,defer 语句可以用来在函数退出前执行一些必要的清理工作,比如关闭文件或者释放锁等操作。在 defer 语句中,如果使用了函数参数,那么在 defer 语句执行时,会对参数进行取值并将其压入栈中。但需要注意的是,由于 defer 的实现方式,如果在 defer 语句执行时变量已经被修改,那么 defer 执行时获取的变量值可能和预期不一致。

下面是一个示例代码,演示了 defer 的变量快照失效的情况:

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. x := 1
  7. defer func() {
  8. fmt.Println("defer x =", x)
  9. }()
  10. x++
  11. fmt.Println("x =", x)
  12. }

输出结果为:

  1. x = 2
  2. defer x = 1

可以看到,在 defer 语句中,变量 x 的值被快照为 1,而不是预期的 2。这是因为在 defer 语句执行时,x 的值已经被修改,所以获取到的值是之前的值。

要避免这种情况,可以将变量复制一份,在 defer 语句中使用复制后的变量。例如:

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. x := 1
  7. y := x
  8. defer func() {
  9. fmt.Println("defer x =", y)
  10. }()
  11. x++
  12. fmt.Println("x =", x)
  13. }

输出结果为:

  1. x = 2
  2. defer x = 1

可以看到,在 defer 语句中,使用了复制后的变量 y,所以获取到的值为 1,与预期一致。


该分类下的相关小册推荐: