defer概念
defer其实就相当于Java中的try{}finally{}中finally用法.我们看一下defer的定义:
简单使用:
func tryDefer() {
file, err := os.Open("README.md")
if err!=nil {
panic(err)
}
defer file.Close()//直接在这里写下关闭就好,需要管顺序
loop.PrintContentFile(file)//这是之前介绍文件读取定义的,打印文件函数
}
特性
- 确保调用函数在结束时(代码执行完或return)发生.这个于Java的finally代码块使用.
- 参数在defer语句时计算
func tryDefer() {
for i := 0; i < 100; i++ {
defer fmt.Println(i)
if i == 10 {
panic("num too big")
}
}
}
打印:
10
9
8
7
6
5
4
3
2
1
0
panic: num too big
goroutine 1 [running]:
main.tryDefer()
/Users/cdz/go/src/com.cdz/learngo/errhandling/defer/defer.go:29 +0x183
main.main()
/Users/cdz/go/src/com.cdz/learngo/errhandling/defer/defer.go:36 +0x20
从打印过程可以看出,defer语句后使用的参数,在调用时就已经计算,且进入defer栈内,最后当函数退出时,遵循先进后出的原则.
- defer列表为后进先出
func tryDefer() {
defer fmt.Println(2)
fmt.Println(1)
defer fmt.Println(3)
return
}
打印:
1
3
2
说明在defer中,只有在方法执行完前,或者方法return之前才会执行不影响原有代码, 且多个defer是有一个栈的,遵循后进先出的原则。
综合事例
将 上一篇斐波那契数列写入一个文件中.
func writFile(filename string) {
file, e := os.Create(filename)
if e != nil {
panic(e)
}
defer file.Close() //可以看到正常使用时去关闭就好,不需要过多注意
writer := bufio.NewWriter(file)
defer writer.Flush()
fibonacci := fib.Fibonacci()
for i:=0;i<=20 ;i++ {
fmt.Fprintln(writer,fibonacci())
}
}
defer使用场景
- open/close
- lock/unlock
- priintHeader/printFooter
作者所有的学习源码在 go学习源码github地址,如果觉得有用的话帮小智贡献一个star😁