关键字之defer、panic、recover

一、defer      

         1、 defer延迟调用,完成一些收尾工作。无论函数或方法是否出错,一定会在退出当前函数或者方法之前调用传入的函数(只对函数或方法生效,代码块不生效),常被用于关闭文件描述符、关闭数据库连接以及解锁资源。

        2、defer的实现原理

        编译器会将 defer 关键字都转换成 runtime.deferproc 函数,负责创建新的延迟调用;runtime.deferreturn 函数负责在函数调用结束时执行所有的延迟调用,runtime.deferreturn 函数会多次判断当前 Goroutine 的 _defer 链表中是否有未执行的剩余结构,在所有的延迟函数调用都执行完成之后,该函数才会返回。

        3、多次调用 defer 时的执行顺序问题:

        后调用的defer函数会先执行,先调用的defer函数会后执行。内部其实是一个defer链表,会绑定到当前的goroutine

   defer 关键字插入时是从后向前的,而 defer 关键字执行是从前向后的,而这就是后调用的 defer 会优先执行的原因。

preview


       4、 defer的传值方式及预计算问题:
        defer的传值采用值传递,调用defer时会立刻对函数中引用的外部参数进行拷贝进行值传递,导致实际执行时。

func main() {
    startedAt := time.Now()
    defer fmt.Println(time.Since(startedAt))
    time.Sleep(time.Second)
}


        解决此问题可以向 defer 关键字传入匿名函数,虽然调用defer时也使用值传递,但是因为拷贝的是函数指针,所以 time.Since(startedAt) 会在 main 函数返回前被调用并打印出符合预期的结果。

func main() {
    startedAt := time.Now()
    defer func() { fmt.Println(time.Since(startedAt)) }()
    time.Sleep(time.Second)
}

二、panic和recover

panic,调用panic时会立刻停止执行函数的其他代码,并触发当前Goroutine的defer链表(defer要定义在panic之前,否则defer不生效);
recover,可以中止panic造成的程序崩溃,且只能定义在defer中。

触发panic时,会先打印defer的函数再打印异常堆栈信息

package main  import "fmt"  func main() { defer func() { fmt.Println("a")
   }() defer func() { fmt.Println("b")
   }() defer func() { fmt.Println("c")
   }() panic("error")
}

打印:
GOROOT=D:\Go #gosetup
GOPATH=D:\goland\workspace #gosetup
D:\Go\bin\go.exe build -o C:\Users\80310624\AppData\Local\Temp\___1go_build_main_go.exe D:\goland\workspace\src\proj_test01\main.go #gosetup
C:\Users\80310624\AppData\Local\Temp\___1go_build_main_go.exe #gosetup
c
b
a
panic: error


goroutine 1 [running]:
main.main()
        D:/goland/workspace/src/proj_test01/main.go:15 +0x85


Process finished with exit code 2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值