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!")
}

输出:

In Function1 at the top
In Function1 at the bottom!
Function2: Deferred until the end of the calling function!

请将 defer 关键字去掉并对比输出结果。

使用 defer 的语句同样可以接受参数,下面这个例子就会在执行 defer 语句时打印 0

func a() {
i := 0
defer fmt.Println(i)
i++
return
}

当有多个 defer 行为被注册时,它们会以逆序执行(类似栈,即后进先出):

func f() {
for i := 0; i < 5; i++ {
defer fmt.Printf("%d ", i)
}
}

上面的代码将会输出:4 3 2 1 0

关键字 defer 允许我们进行一些函数执行完成后的收尾工作,例如:

  1. 关闭文件流:

    // open a file defer file.Close() (详见第 12.2 节)

  2. 解锁一个加锁的资源

    mu.Lock() defer mu.Unlock() (详见第 9.3 节)

  3. 打印最终报告

    printHeader() defer printFooter()

  4. 关闭数据库链接

    // open a database connection defer disconnectFromDB()

合理使用 defer 语句能够使得代码更加简洁。

使用 defer 语句实现代码追踪

一个基础但十分实用的实现代码执行追踪的方案就是在进入和离开某个函数打印相关的消息,即可以提炼为下面两个函数:

func trace(s string) { fmt.Println("entering:", s) }
func untrace(s string) { fmt.Println("leaving:", s) }

以下代码展示了何时调用两个函数:

示例 6.10 defer_tracing.go:

package main

import "fmt"

func trace(s string)   { fmt.Println("entering:", s) }
func untrace(s string) { fmt.Println("leaving:", s) } func a() {
trace("a")
defer untrace("a")
fmt.Println("in a")
} func b() {
trace("b")
defer untrace("b")
fmt.Println("in b")
a()
} func main() {
b()
}

输出:

entering: b
in b
entering: a
in a
leaving: a
leaving: b

使用 defer 语句来记录函数的参数与返回值——利用了defer是在return后的特性哇!!!

下面的代码展示了另一种在调试时使用 defer 语句的手法(示例 6.12 defer_logvalues.go):

package main

import (
"io"
"log"
) func func1(s string) (n int, err error) {
defer func() {
log.Printf("func1(%q) = %d, %v", s, n, err)
}()
return 7, io.EOF
} func main() {
func1("Go")
}

输出:

Output: 2011/10/04 10:46:11 func1("Go") = 7, EOF

最新文章

  1. ajax内调用WCF服务
  2. ucenter的单点登录
  3. 更换centos源
  4. 【转】d3d的投影矩阵推导
  5. 数模学习笔记(四)——AHP
  6. 纯CSS3动画:一棵跳舞的树
  7. Node.js在任意目录下使用express命令‘不是内部或外部命令’解决方法
  8. TypeError: Error #1006: value 不是函数。
  9. FFT总结
  10. Linux(Ubuntu)使用日记------为程序添加桌面快捷方式
  11. golang初识 - install go on ubuntu
  12. Python学习笔记4基本数据类型续
  13. vue_drf之实现极验滑动验证码
  14. webpack的总结
  15. Linux_CentOS-服务器搭建 &lt;四&gt;
  16. APP-4-百度地图定位
  17. 2.3Python基础语法(三)之输入输出
  18. SVN服务器搭建和使用-转载
  19. ubuntu16.4中安装samba服务
  20. python3.7 安装pyqt5

热门文章

  1. 梦想CAD控件打印相关
  2. ThinkPHP---thinkphp框架介绍
  3. docker 1--&gt;docker swarm 转载
  4. TWaver3D特效之高光反射
  5. php第二十三节课
  6. enote笔记法的思考
  7. 洛谷——P1775 古代人的难题_NOI导刊2010提高(02)&amp;&amp; P1936 水晶灯火灵(斐波那契数列)
  8. C/C++学习)22.QTcpServer、QTcpSocket、QUdpSocket使用
  9. Python单例模式的实现方式
  10. python面试题之如何在Python中创建自己的包