Go语言的Defer函数

Golang defer function

Defer的特点

  • 确保调用在函数结束时发生

  • 参数在defer语句时计算

  • defer列表为后进先出

确保调用在函数结束时发生

下面的例子中,fmt.Println(1)会比fmt.Println(2)晚执行。

func tryDefer() {
	defer fmt.Println(1)
	fmt.Pintln(2)
	panic("error"
}
func main() {//
	tryDefer()
}

再看一个文件的例子

package main

import (
	"fmt"
	"os"
	"bufio"
	"imooc.com/ccmouse/learngo/lang/functional/fib"
)

func writeFile(filename string) {
	file, err := os.OpenFile(filename,
		os.O_EXCL|os.O_CREATE|os.O_WRONLY, 0666)

	if err != nil {
		if pathError, ok := err.(*os.PathError); !ok {
			panic(err)
		} else {
			fmt.Printf("%s, %s, %s\n",
				pathError.Op,
				pathError.Path,
				pathError.Err)
		}
		return
	}
	defer file.Close()

	writer := bufio.NewWriter(file)
	defer writer.Flush()

	f := fib.Fibonacci()
	for i := 0; i < 20; i++ {
		fmt.Fprintln(writer, f())
	}
}

func main() {
	writeFile("fib.txt")
}

参数在defer语句时计算 / defer列表为后进先出

关于参数在defer语句时计算,可以看这个例子。

package main

import (
	"fmt"
	"os"

	"bufio"

	"imooc.com/ccmouse/learngo/lang/functional/fib"
)

func tryDefer() {
	for i := 0; i < 100; i++ {
		defer fmt.Println(i)
		if i == 30 {
			panic("printed too many")
		}
	}
}

func main() {
	tryDefer()
}

得到下面的结果,可以看到defer是从10开始打印的,说明后进先出。

然后程序在10的时候停住了,但是并没有打印10个10,说明参数在defer语句时计算。

10
9
8
7
6
5
4
3
2
1
0
panic: printed too many

何时使用defer

  • open/close

  • lock/unlock

  • printheader/pringfooter

Last updated