Golang学习笔记

记录一些学习的内容

defer的坑

defer是Golang的一个特色,称为“延迟调用函数”。在外部函数返回之后才会被调用执行。相较于C系代码需要适时的添加内存管理的代码。defer的特性,大大降低了内存管理的成本(创建的同时做好defer声明即可)。
样例代码

1
2
3
4
5
6
func test(){
defer func(){ fmt.Println("defer") }()//声明defer
//TODO
return
//defer实际执行位置
}

但,似乎这样就能很浅显的说,defer的这个特性就已经学完了吗?直到我在网上看到了这样的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func test() error { //错误的代码
f, err := os.Open("A.txt")
if err != nil {
return err
}

defer func() { f.Close() }()

f, err = os.Open("B.txt")
if err != nil {
return err
}

defer func() { f.Close() }()
 defer func() { fmt.PrintIn("1")}
 defer func() { fmt.PrintIn("2")}

return nil
}

运行结果如何?
和通常一样,文件操作伴随着对文件句柄的打开和关闭,由于先前所说,defer定义的代码实际运行是在函数返回之后,那么也就不难理解,因为f变量被再一次赋值,所以上述代码的A.txt文件句柄实际上并没有被释放掉,只释放掉了B.txt。
那实际控制台输出了什么?
先跑一下在说。执行结果输出了:2,1,也就是符合先入后出的原则。