go 中 defer 语句默认捕获的是变量声明时的值(按值传递),若需打印变量在 defer 执行时的最新值,应使用匿名函数闭包显式捕获变量引用。
go 中 defer 语句默认捕获的是变量声明时的值(按值传递),若需打印变量在 defer 执行时的最新值,应使用匿名函数闭包显式捕获变量引用。
在 Go 中,defer 语句的参数在 defer 语句执行时即被求值并保存(即“延迟求值”仅针对函数调用本身,而非其参数),这意味着变量的值在 defer 被注册那一刻就被固定。例如:
err := errors.New("error 1")defer fmt.Println(err) // 此处 err 已被求值为 "error 1" 的错误实例err = errors.New("error 2") // 这行不会影响已注册的 defer
上述代码最终输出 "error 1",而非预期的 "error 2"。
✅ 正确做法是将 fmt.Println(err) 封装进一个匿名函数,并通过闭包引用 err 变量——这样实际打印发生在 defer 执行时(即函数退出前),此时读取的是 err 的当前值:
package mainimport ( "errors" "fmt")func main() { err := errors.New("error 1") defer func() { fmt.Println(err) // 闭包捕获 err 变量(地址引用),运行时取最新值 }() err = errors.New("error 2") // 输出:error 2}
⚠️ 注意事项:
总结:要实现 defer 中“动态取值”,核心是用闭包延迟求值,而非依赖 defer 参数的静态绑定。这是 Go 并发安全与控制流设计中的重要实践模式。