Golang轻松学习
个人博客站点:
简书: 😽 猫轻王 https://www.jianshu.com/u/6cce817646be
掘金: 😽 猫轻王 https://juejin.cn/user/1640918680347453
CSDN: 😽 猫轻王 https://blog.csdn.net/moer0
个人项目主页:https://github.com/moercat
Go语言的 defer 语句会将其后面跟随的语句进行延迟处理,在 defer 归属的函数即将返回时,将延迟处理的语句按 defer 的逆序进行执行,也就是说,先被 defer 的语句最后被执行,最后被 defer 的语句,最先被执行。
代码如下(示例):
package main
import (
"fmt"
)
func main() {
deferCall()
}
func deferCall() {
defer func() { fmt.Println("打印前") }()
defer func() { fmt.Println("打印中") }()
defer func() { fmt.Println("打印后") }()
panic("触发异常")
}
输出:
打印后
打印中
打印前
panic: 触发异常
原理:
其实golang 中的defer 关键字会在 main 函数所有语句之后,return 之前时候调用
压栈式执行,也就是说先注册的函数后调用。
如上,我们注册的顺序式 前,中,后,最后打印结果自然是反着来的,程序输出:
打印后 打印中 打印前
最终才 panic: 触发异常
也就是压栈式执行的逻辑,栈会遵循先进后出原则,每个defer语句都相当于执行一次进栈操作,之后在函数所有语句之后,return 之前时候依次出栈,那么晚进栈的自然早出栈。
代码如下(示例):
package main
import (
"fmt"
)
func main() {
deferError()
}
func deferError() {
defer func() { fmt.Println("打印前") }()
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
}()
defer func() { fmt.Println("打印中") }()
defer func() { fmt.Println("打印后") }()
panic("触发异常")
}
输出:
打印后
打印中
触发异常
打印前
由于recover 在defer 内提前声明,且defer语句在panic之前,那么defer在所有语句执行结束后便会执行,此时recover 接收到当前程序内的panic抛出的error。程序则不会因为错误中断,而会执行defer内的程序,也就是该程序的 fmt.Println(err)语句,由于defer依旧遵循着先进后出原则,那么即使panic在defer执行前便已运行,却被捕获在defer中间打印
通过以上两个例子可以轻松了解在Golang中defer的使用方式,defer在我们工作中的重要性不言而喻。由于错误捕获与在程序运行后执行的逻辑,非常适合我们的编写中间与进行自定义的错误处理,或者将程序依次上抛进行捕获。
希望这个博客能对你有所益处。我是轻王,我为自己代言。