1.只需要在调用普通函数或方法前加上关键字defer,就完成了defer所需要的语法。当defer语句被执行时,跟在defer后面的函数会被延迟执行。直到包含该defer语句的函数执行完毕时,defer后的函数才会被执行,不论包含defer语句的函数是通过return正常结束,还是由于panic导致的异常结束

2.defer语句经常被用于处理成对的操作,如打开、关闭、连接、断开连接、加锁、释放锁。通过defer机制,不论函数逻辑多复杂,都能保证在任何执行路径下,资源被释放。释放资源的defer应该直接跟在请求资源的语句后

3.defer语句会先调用,defer后面的函数会最后调用,两层函数,配合返回匿名函数函数值实现trace功能
defer trace("bigSlowOperation")()

4.http响应写入文件 n, err = io.Copy(f, resp.Body)

练习5.18:不修改fetch的行为,重写fetch函数,要求使用defer机制关闭文件。

package main

//导入io/ioutil和net/http包
import (
"fmt"
"io"
"os"
//"io/ioutil"
"net/http"
"strings"
//"time"
"net/url"
)
/*
练习5.18:不修改fetch的行为,重写fetch函数,要求使用defer机制关闭文件。
*/
func main() {
//开始时间
//start := time.Now()
//for循环命令行参数
for _, u := range os.Args[1:] {
//加入前缀
if !strings.HasPrefix(u, "http://") {
u = "http://" + u
}
res, err := http.Get(u)
//判断错误
if err != nil {
//向标准错误流打印信息
fmt.Fprintf(os.Stderr, "fetch:%v \n", err)
//终止进程
os.Exit(1)
}
//使用defer机制
defer res.Body.Close() urlObj, _ := url.Parse(u)
filename := urlObj.Path
if filename == "/" {
filename = "index.html"
}
var f *os.File
f, err = os.Create(filename)
//使用defer机制
/*
我们没有对f.close采用defer机制,因为这会产生一些微妙的错误。许多文件系统,尤其是NFS,写入文件时发生的错误会被延迟到文件关闭时反馈。如果没有检查文件关闭时的反馈信息,可能会导致数
据丢失,而我们还误以为写入操作成功。如果io.Copy和f.close都失败了,我们倾向于将io.Copy的错误信息反馈给调用者,因为它先于f.close发生,更有可能接近问题的本质。
*/
defer f.Close()
_, err = io.Copy(f, res.Body)
//判断错误
if err != nil {
//向标准错误流打印信息
fmt.Fprintf(os.Stderr, "fetch:%v \n", err)
//终止进程
os.Exit(1)
}
}
}

  

[日常] Go语言圣经-Deferred函数的更多相关文章

  1. [日常] Go语言圣经-匿名函数习题

    Go语言圣经-匿名函数1.拥有函数名的函数只能在包级语法块中被声明,通过函数字面量(function literal),我们可绕过这一限制,在任何表达式中表示一个函数值2.通过这种方式定义的函数可以访 ...

  2. [日常] Go语言圣经-匿名函数习题2

    练习5.13: 修改crawl,使其能保存发现的页面,必要时,可以创建目录来保存这些页面.只保存来自原始域名下的页面.假设初始页面在golang.org下,就不 要保存vimeo.com下的页面. p ...

  3. [日常] Go语言圣经-函数多返回值习题

    Go语言圣经-函数多返回值1.在Go中,一个函数可以返回多个值2.许多标准库中的函数返回2个值,一个是期望得到的返回值,另一个是函数出错时的错误信息3.如果一个函数将所有的返回值都显示的变量名,那么该 ...

  4. [日常] Go语言圣经-Panic异常,Recover捕获异常习题

    Go语言圣经-Panic异常1.当panic异常发生时,程序会中断运行,并立即执行在该goroutine中被延迟的函数(defer 机制)2.不是所有的panic异常都来自运行时,直接调用内置的pan ...

  5. [日常] Go语言圣经-错误,函数值习题

    Go语言圣经-错误 1.panic异常.panic是来自被调函数的信号,表示发生了某个已知的bug 2.任何进行I/O操作的函数都会面临出现错误的可能 3.错误是软件包API和应用程序用户界面的一个重 ...

  6. [日常] Go语言圣经--结构体,JSON习题

    Go语言圣经-结构体 1.结构体是一种聚合的数据类型,是由零个或多个任意类型的值聚合成的实体 2.通常一行对应一个结构体成员,成员的名字在前类型在后,不过如果相邻的成员类型如果相同的话可以被合并到一行 ...

  7. [日常] Go语言圣经--复合数据类型,数组习题

    go语言圣经-复合数据类型 1.以不同的方式组合基本类型可以构造出来的复合数据类型 2.四种类型——数组.slice.map和结构体 3.数组是由同构的元素组成——每个数组元素都是完全相同的类型——结 ...

  8. [日常] Go语言圣经--复数,布尔值,字符串习题

    go语言圣经-复数 1.我们把形如a+bi(a,b均为实数)的数称为复数,其中a称为实部,b称为虚部,i称为虚数单位.两种精度的复数类型:complex64和complex128,分别对应float3 ...

  9. [日常] Go语言圣经--作用域,基础数据类型,整型

    go语言圣经-作用域 1.一个声明语句将程序中的实体和一个名字关联,比如一个函数或一个变量 2.一个变量的生命周期是指程序运行时变量存在的有效时间段;声明语句的作用域对应的是一个源代码的文本区域,它是 ...

随机推荐

  1. MicrosoftSQLServer数据库定时备份(备份计划)的几种方式

    首先,做备份计划钱,先要查看下SQL Server代理是否开启 进入主题 1.备份计划方式1: 1.1新增数据库备份作业: 备份脚本: declare @name varchar() ))+'.bak ...

  2. ubuntu14.04 下出现 libmysqlclient.so.20 找不到问题

    解决办法: apt-get install libzdb-dev

  3. Color the ball(HDU1556)树状数组

    每次对区间内气球进行一次染色,求n次操作后后所有气球染色次数. 树状数组,上下区间更新都可以,差别不大. 1.对于[x,y]区间,对第x-1位减1,第y位加1,之后向上统计 #include<b ...

  4. HDU - 2604 Queuing(递推式+矩阵快速幂)

    Queuing Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  5. iOS--各种bug详解

    1.为什么传的参数都对,但是就是请求不下来数据. 答:检查下传的字符串中,是不是有多的空格. 例如: 错误:{"startIndex":"1","en ...

  6. 装饰器中的@functools.wraps的作用

    def login_required(view_func): @functools.wraps(view_func) def wrapper(*args, **kwargs): ...... retu ...

  7. W,b的初始化和几种激活函数

    权重W不能全部初始化为0,原因很简单,我们可以自己在本子上推导一下,假设现有一个含有一个隐藏层,隐藏层含有两个神经元初始输入为两个向量的网络,如果权重初始化全部为0,那么,第一层的输出,会和第二层的输 ...

  8. Windows平台下搭建自己的Git服务器

    该文章转自:http://www.codeceo.com/article/windows-git-server.html Gitblit 是一个纯 Java 库用来管理.查看和处理 Git 资料库,相 ...

  9. POJ 2603

    #include<iostream> #include<stdio.h> #define M 350000 #define N 30000 using namespace st ...

  10. shell信号捕捉命令 trap

    trap 命令 tarp命令用于在接收到指定信号后要执行的动作,通常用途是在shell脚本被中断时完成清理工作.例如: 脚本在执行时按下CTRL+c时,将显示"program exit... ...