defer 是go语言中一个强大且常用的关键字,用于安排函数调用在当前函数执行完毕(无论是正常返回、panic 还是 return 语句)之前执行。其核心特性包括:
语法示例:
lock(l); defer unlock(l); // unlock(l) 会在当前函数返回前执行 // 循环中的 defer 示例 // 这段代码会在当前函数返回前,以 3 2 1 0 的顺序打印 for i := 0; i <= 3; i++ { defer fmt.Print(i) // i 的值在 defer 语句执行时(即循环的每次迭代中)被捕获 }
在上述循环示例中,当 i 为 0 时,defer fmt.Print(0) 被推入栈;当 i 为 1 时,defer fmt.Print(1) 被推入栈,以此类推。因此,当函数返回时,栈顶的 fmt.Print(3) 先执行,然后是 fmt.Print(2),最终是 fmt.Print(0)。
Go语言推崇显式错误处理,但对于程序中不可恢复的错误或异常情况,提供了 panic 和 recover 机制。defer 在此机制中扮演着至关重要的角色,它提供了一个在 panic 发生后执行清理或恢复操作的机会。
panic 和 recover 结合 defer 的示例:
立即学习“go语言免费学习笔记(深入)”;
package main import "fmt" func main() { f() fmt.Println("Returned normally from f.") // 这行代码会在 f() 中的 panic 被 recover 后执行 } func f() { // defer 函数用于捕获 panic defer func() { if r := recover(); r != nil { fmt.Println("Recovered in f", r) // 捕获到 panic,并打印恢复信息 } }() fmt.Println("Calling g.") g(0) // 调用 g(),g() 中可能会发生 panic fmt.Println("Returned normally from g.") // 如果 g() 发生 panic 并被 recover,这行代码不会执行 } func g(i int) { if i > 3 { fmt.Println("Panicking!") panic(fmt.Sprintf("%v", i)) // 当 i > 3 时触发 panic } // defer 函数,会在 g() 返回前执行,即使发生 panic 也会执行 defer fmt.Println("Defer in g", i) fmt.Println("Printing in g", i) g(i + 1) // 递归调用 g() }
代码执行流程分析:
输出结果:
Calling g. Printing in g 0 Printing in g 1 Printing in g 2 Printing in g 3 Panicking! Defer in g 4 Defer in g 3 Defer in g 2 Defer in g 1 Defer in g 0 Recovered in f 4 Returned normally from f.
defer 语句在Go语言中被广泛用于以下场景:
file, err := os.Open("example.txt") if err != nil { return err } defer file.Close() // 确保文件在函数返回时关闭 // ... 对文件进行操作
mu.Lock() defer mu.Unlock() // 确保锁在函数返回时释放 // ... 临界区操作
start := time.Now() defer func() { fmt.Printf("Execution took %v\n", time.Since(start)) }() // ... 需要计时的代码
func example() (result int) { defer func() { result = 100 // 在函数返回前修改返回值 }() return 10 } fmt.Println(example()) // 输出 100
func a() { i := 0 defer fmt.Println(i) // i 在此处被求值为 0 i++ return } // 调用 a() 会输出 0
defer 语句是Go语言中一个独特且强大的特性,它极大地简化了资源管理、错误处理以及代码的清理工作。通过理解其延迟执行、参数立即求值以及LIFO执行顺序的特性,开发者可以编写出更加健壮、简洁且易于维护的Go程序。尤其是在与 panic 和 recover 结合使用时,defer 提供了一种优雅的方式来处理程序中的非预期错误,使得Go程序在面对异常情况时也能保持一定的韧性。掌握 defer 的正确使用,是Go语言专业开发的关键一步。
以上就是Go语言中 defer 语句的深度解析与实践的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号