defer 把函数调用压入当前 goroutine 的 defer 栈,在外层函数返回前按 LIFO(后进先出)顺序执行。关键点:defer 语句执行时,调用的参数立即求值并保存,推迟的只是函数体执行;但如果是 defer func(){...}() 闭包形式,闭包内捕获的是变量本身,执行时读到的是最新值。
defer 还能读取和修改命名返回值,这是 recover 和统一错误包装的常用手段。性能上 Go 1.14 引入开放编码(open-coded)defer 后,普通场景开销已接近零,不必因性能回避。
func f() (r int) {
i := 1
defer func(v int) { fmt.Println("param:", v) }(i) // 立即求值,打印 1
defer func() { fmt.Println("closure:", i) }() // 闭包,打印 2
defer func() { r += 10 }() // 修改命名返回值
i = 2
return i // 先执行返回赋值 r=2,再跑 defer,最终 r=12
}
易错点:循环里 defer 文件关闭会累积到函数结束才释放,应包一层匿名函数。追问方向:defer 与 panic/recover 的配合、return 与 defer 的精确执行次序。