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

go语言笔记——defer作用DB资源等free或实现调试的更多相关文章

  1. Go 语言笔记

    Go 语言笔记 基本概念 综述 Go 语言将静态语言的安全性和高效性与动态语言的易开发性进行有机结合,达到完美平衡. 设计者通过 goroutine 这种轻量级线程的概念来实现这个目标,然后通过 ch ...

  2. C语言笔记(一)

    笑话一枚:程序员 A:“哥们儿,最近手头紧,借点钱?”程序员 B:“成啊,要多少?”程序员 A:“一千行不?”程序员 B:“咱俩谁跟谁!给你凑个整,1024,拿去吧.” =============== ...

  3. 009-数组-C语言笔记

    009-数组-C语言笔记 学习目标 1.[掌握]数组的声明 2.[掌握]数组元素的赋值和调用 3.[掌握]数组的初始化 4.[掌握]数组的遍历 5.[掌握]数组在内存中的存储 6.[掌握]数组长度计算 ...

  4. 007-函数-C语言笔记

    007-函数-C语言笔记 学习目标 1.[了解]函数的分类 2.[掌握]函数的声明定义和调用 3.[掌握]函数的形参和实参 4.[掌握]带返回值的函数 5.[掌握]全局变量和局部变量 6.[了解]注释 ...

  5. 005-循环结构(上)-C语言笔记

    005-循环结构(上)-C语言笔记 学习目标 1.[掌握]switch-case结构 2.[理解]case语句穿透 3.[理解]Xcode断点调试 4.[理解]while循环结构初体验 5.[掌握]w ...

  6. 004-流程控制-C语言笔记

    004-流程控制-C语言笔记 学习目标 1.[掌握]关系运算符和关系表达式 2.[掌握]逻辑运算符和逻辑表达式 3.[掌握]运算符的优先级和结合性 4.[掌握]if-else if-else结构的使用 ...

  7. 002-IDE的使用与数据类型-C语言笔记

    002-IDE的使用与数据类型-C语言笔记 学习目标 1.[了解]IDE并熟悉Xcode基本使用技巧 2.[理解]C程序的入口和运行流程 3.[理解]变量的声明赋值和一些细节 4.[理解]变量的命名规 ...

  8. 001-iOS开发前奏-C语言笔记

    001-iOS开发前奏-C语言笔记 学习目标 1.[了解]操作系统 2.[了解]应用软件 3.[了解]操作系统的分类和市场占有份额 4.[了解]iOS操作系统 5.[了解]应用软件开发的分类 6.[了 ...

  9. Go语言笔记[实现一个Web框架实战]——EzWeb框架(一)

    Go语言笔记[实现一个Web框架实战]--EzWeb框架(一) 一.Golang中的net/http标准库如何处理一个请求 func main() { http.HandleFunc("/& ...

随机推荐

  1. centos 搭建pptp

    很多朋友不会在CENTOS 在安装vpn,因为对于菜鸟来说安装VPN的确是个头晕的事情,特别是安装openvpn,不过安装pptp就稍微简单一点,国内网上有很多安装pptp的教程,但是都很繁杂,我在国 ...

  2. RabbitMQ系列(八)--顺序消费模式和迅速消息发送模式

    MQ使用过程中,有些业务场景需要我们保证顺序消费,而如果一个Producer,一个Queue,多个Consumer的情况下是无法保证顺序的 举例: 1.业务上产生三条消息,分别是对数据的增加.修改.删 ...

  3. JAVA基础——集合Iterator迭代器的实现

    一.迭代器概述 1.什么是迭代器? 在Java中,有很多的数据容器,对于这些的操作有很多的共性.Java采用了迭代器来为各种容器提供了公共的操作接口.这样使得对容器的遍历操作与其具体的底层实现相隔离, ...

  4. Python利用带权重随机数解决抽奖和游戏爆装备问题

    关于带权随机数 为了帮助理解,先来看三类随机问题的对比: 1.已有n条记录,从中选取m条记录,选取出来的记录前后顺序不管. 实现思路:按行遍历所有记录,约隔n/m条取一个数据即可 2.在1类情况下,还 ...

  5. Promise对象和回调函数,解决异步数据传递问题

    下面的代码例子,均已小程序的异步请求数据为案例来说明 1.利用回调函数,来解决异步数据传递问题 异步操作api.js const getBooks = (url, callback) => { ...

  6. 洛谷 2824 [HEOI2016/TJOI2016]排序

    [题意概述] 对一个1到n的排列做m次区间排序,最后询问位置q上面的数. [题解] 区间排序的效率是nlogn,所以暴力做的话效率是mnlogn,显然达不到要求. 我们考虑二分答案.如果某个位置的数比 ...

  7. MVC 中如果js,css文件放到视图文件夹无法访问的解决办法

    在视图配置文件web.config 中添加如下节点,注意:此web.config 是视图文件夹中的,在你的views视图中可以找到<system.webServer>开头的<hand ...

  8. Convolutions in TensorFlow

    Convolutions in TensorFlow Convolutions without training You might already be familiar with the term ...

  9. HDU 1159 LCS最长公共子序列

    #include <cstdio> #include <cstring> using namespace std; ; #define max(a,b) a>b?a:b ...

  10. validate针对checkbox、radio、select标签的验证

    jQuery.validate 是jquery的一个插件,用来辅助开发者在客户端方便快捷的实现表单验证,最终达到提高用户体验的目的. 示例代码 <form id="formLogin& ...