
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()) // 输出 100func a() {
i := 0
defer fmt.Println(i) // i 在此处被求值为 0
i++
return
}
// 调用 a() 会输出 0defer 语句是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号