教程集 www.jiaochengji.com
教程集 >  Golang编程  >  golang教程  >  正文 golang中的defer recover panic

golang中的defer recover panic

发布时间:2022-03-06   编辑:jiaochengji.com
教程集为您提供golang中的defer recover panic等资源,欢迎您收藏本站,我们将为您提供最新的golang中的defer recover panic资源
<h1>defer</h1>

先看下面代码

<pre><code class="lang-go hljs">func main() { deferCall() fmt.Println("exit main") } func deferCall() { defer fmt.Println("defer 1") defer func() { fmt.Println("defer 2")}() panic("异常") defer func() { fmt.Println("defer 3") if p := recover(); p != nil { fmt.Println("recover", p) } }() time.Sleep(time.Second * 3) fmt.Println("after panic") } </code></code></pre>

执行结果是:

<pre><code class="lang-go hljs">defer 2 defer 1 panic: 异常 goroutine 1 [running]: main.deferCall() Process finished with exit code 2 </code></code></pre>

结论:

<ol><li>defer本身也是一条语句,会按函数过程执行</li> <li> defer后面跟的函数,会延迟到所在函数退出时执行
当defer语句被执行时,它后面的函数会被延迟执行,延迟到它所在的函数退出时刻前执行。</li> <li> panic是函数异常退出的点,panic之后的语句不会执行
panic同return语句都为函数的退出点,return是正常退出,panic是异常退出,先执行defer后的函数,再return或panic。panic之后声明的defer函数都不会执行</li> <li> 逆序执行
多条defer语句时,它后面的函数执行顺序与声明顺序相反</li> <li>recover要在panic之前声明,否则不能捕获到异常</li> </ol><h5>特别说明:</h5>

上面的执行打印结果在终端每次输出都一样,但如果在goland IDE中,输出可能会是先panic: 异常,再defer 2 defer 1。这是因为程序是作为goland的子进程执行的,子进程的stdout,stderr分别通过管道重定向到Goland父进程,因此子进程的fmt.println与panic输出可能会出现乱序的情况。
详细参考:Golang中panic和defer的字符串打印顺序

<h1>recover</h1>

先看如下代码

<pre><code class="lang-go hljs">func deferCall2() { defer fmt.Println("defer 1") defer func() { fmt.Println("defer 2")}() defer func() { fmt.Println("defer 3") if p := recover(); p != nil { fmt.Println("recover", p) } }() defer func() { fmt.Println("defer 4")}() panic("异常") time.Sleep(time.Second * 3) fmt.Println("after panic") } </code></code></pre>

执行结果:

<pre><code class="lang-go hljs">defer 4 defer 3 recover 异常 defer 2 defer 1 exit main Process finished with exit code 0 </code></code></pre>

结论:

<ol start="6"><li> panic后,逆序执行defer后的函数,遇到recover内置函数后
recover会使程序从panic中恢复,并返回panic value</li> </ol><h1>defer实现函数trace log</h1> <pre><code class="lang-go hljs">func deferCall3() { // defer表达式会先求值,故下面defer语句会先调用trace函数求得匿名defer函数 defer trace("deferCall3")() time.Sleep(time.Second * 5) } func trace(msg string) func() { start := time.Now() log.Printf("enter %s", msg) return func() { // start的值,这里牵扯到闭包,上下文的概念 log.Printf("exit %s (%s)", msg, time.Since(start)) } } </code></code></pre>

执行结果:

<pre><code class="lang-go hljs">2019/06/30 21:20:14 enter deferCall3 2019/06/30 21:20:19 exit deferCall3 (5.004000116s) exit main </code></code></pre>

结论:

<ol start="7"><li>验证了结论1,defer本身是一条语句,会按顺序执行准备上下文,只是后面跟的函数会延迟执行</li> </ol>

到此这篇关于“golang中的defer recover panic”的文章就介绍到这了,更多文章或继续浏览下面的相关文章,希望大家以后多多支持JQ教程网!

您可能感兴趣的文章:
golang异常处理机制
recover 没有捕获异常_GO语言异常处理机制panic和recover分析
golang中的defer recover panic
golang中的defer panic recover
Golang - 访问数据库报错后程序继续运行
Go 异常处理机制——defer, error, panic, recover
Golang模仿try & catch
defer ,panic,recover
【Go学习】一道简单Golang面试题中关于panic和defer的执行顺序引发的惨案
Go 学习之路:异常处理defer,panic,recover

[关闭]
~ ~