defer 和追踪
关键字 defer 允许我们推迟到函数返回之前(或任意位置执行 return 语句之后)一刻才执行某个语句或函数(为什么要在返回之后才执行这些语句?因为 return 语句同样可以包含一些操作,而不是单纯地返回某个值)。
关键字 defer 的用法类似于面向对象编程语言 Java 和 C# 的 finally 语句块,它一般用于释放某些已分配的资源。
示例 6.8 defer.go:
package main
import "fmt"
func main() {
function1()
}
func function1() {
fmt.Printf("In function1 at the top\n")
defer function2()
fmt.Printf("In function1 at the bottom!\n")
}
func function2() {
fmt.Printf("Function2: Deferred until the end of the calling function!")
}输出:
请将 defer 关键字去掉并对比输出结果。
使用 defer 的语句同样可以接受参数,下面这个例子就会在执行 defer 语句时打印 0:
当有多个 defer 行为被注册时,它们会以逆序执行(类似栈,即后进先出):
上面的代码将会输出:4 3 2 1 0。
关键字 defer 允许我们进行一些函数执行完成后的收尾工作,例如:
关闭文件流 (详见 第 12.2 节)
解锁一个加锁的资源 (详见 第 9.3 节)
打印最终报告
关闭数据库链接
合理使用 defer 语句能够使得代码更加简洁。
以下代码模拟了上面描述的第 4 种情况:
输出:
使用 defer 语句实现代码追踪
一个基础但十分实用的实现代码执行追踪的方案就是在进入和离开某个函数打印相关的消息,即可以提炼为下面两个函数:
以下代码展示了何时调用这两个函数:
示例 6.10 defer_tracing.go:
输出:
上面的代码还可以修改为更加简便的版本(示例 6.11 defer_tracing2.go):
使用 defer 语句来记录函数的参数与返回值
下面的代码展示了另一种在调试时使用 defer 语句的手法(示例 6.12 defer_logvalues.go):
输出:
链接
Last updated
Was this helpful?