defer 参数求值时机

🟢 简单

题目描述

以下代码的输出是什么?

func main() {
    i := 0
    defer fmt.Println(i)
    i = 10
    fmt.Println("hello")
}

提示

  • defer 的参数在声明时立即求值

解法:理解 defer 参数求值时机

核心概念

defer 的参数在声明时立即求值,而不是执行时。

func example() {
    i := 0
    defer fmt.Println(i) // i = 0,立即求值
    i = 10              // 修改 i 不影响 defer 的参数
}

// 输出:0

如果想获取最新值

使用闭包可以获取执行时的最新值:

func example() {
    i := 0
    defer func() {
        fmt.Println(i) // 闭包,获取最新值
    }()
    i = 10
}

// 输出:10

defer 修改返回值

func example() (result int) {
    defer func() {
        result++ // 修改命名返回值
    }()
    return 0
}

// 返回值:1

对比:值类型 vs 引用类型

func valueExample() {
    i := 0
    defer fmt.Println(i) // 输出 0(值类型)
    i = 10
}

func referenceExample() {
    m := map[string]int{"key": 0}
    defer fmt.Println(m["key"]) // 输出 0(立即求值)
    
    // defer 闭包获取最新值
    defer func() {
        fmt.Println(m["key"]) // 输出 10
    }()
    
    m["key"] = 10
}