本篇文章基于 Golang 1.17.2
书接上回,胖虎前几天面试了一个“双休”的公司,但是他并不想去,他觉得他配不上这么优秀的公司,于是又开始了漫长的面试之路。
面试官:“看你简历上面写着精通 Golang, 那我问个简单的问题吧,什么defer”
胖虎:defer语句注册了一个函数调用,这个调用会延迟到defer语句所在的函数执行完毕后执行,所谓执行完毕是指该函数执行了return语句、函数体已执行完最后一条语句或函数所在的协程发生了panic。
胖虎回答问后,心想:“我厉害吧,把defer语句的官方解释都背下来了,作为优质的八股文选手,快给我发offer吧!!老板,走过路过,不要错过”
面试官看着胖虎自己在那演戏,笑而不语。继续问道:“那你说说为什么需要defer吧”
胖虎:在写代码的时候,经常会需要申请一些资源,比如数据库连接、mysql事务的提交等。
但是经常忘记释资源,并且释放的地方太多
导致很多重复代码,很容易出现事故。
defer关键字就可以解决此类问题,
在函数运行完毕后,释放响应的资源。
面试官:“那你说下defer常见的应用场景吧”
多个defer出现的时候,它是一个“栈”的关系,也就是先进后出。一个函数中,写在前面的defer会比写在后面的defer调用得晚。
package main
import"fmt"
func main(){
defer func1()
defer func2()
defer func3()
}
func func1(){
fmt.Println("func1")
}
func func2(){
fmt.Println("func2")
}
func func3(){
fmt.Println("func3")
}
执行结果如下:
原因如下
package main
import"fmt"
func main(){
test()
}
func test() string{
defer fmt.Println("我是defer")
return testRet()
}
func testRet() string{
fmt.Println("我是testRet")
return""
}
执行结果如下:
结论为:return之后的语句先执行,defer后的语句后执行
package main
import "fmt"
func main() {
defer func() {
if err := recover(); err != nil {
fmt.Printf("err信息是:%+v\n", err)
}
}()
panic("我是panic")
}
执行结果如下:
结论为:遇到panic时,遍历本协程的defer链表,并执行defer。在执行defer过程中:遇到recover则停止panic,返回recover处继续往下执行。
package main
import (
"fmt"
"os"
)
func main() {
defer func() {
fmt.Printf("我是defer信息")
}()
os.Exit(1)
}
执行结果如下:
结论:当发生panic时,defer会被执行,但是当调用os.Exit()方法退出程序时,defer并不会被执行。
package main
import (
"fmt"
)
func main() {
fmt.Println(test())
}
func test() (res string) {
res = "res"
defer func() {
res = "我是defer"
}()
return "我是最终结果"
}
最终结果是:
原因:
package main
import (
"fmt"
)
func main() {
fmt.Println(test())
}
func test() string {
res := "res"
defer func() {
res = "我是defer"
}()
return "我是最终结果"
}
执行结果是:
执行步骤:
总结如下:
胖虎一口气说了这么多,内心想:这次志在必得啊。我明天就能入职,快找我进来吧
面试官:小伙子不错啊,这样吧,在面试你最后一题,你要是能答上来,薪资大胆要,要多少,我们就给多少。
以下代码执行结果是什么?为什么?
package main
import (
"fmt"
)
func main() {
test()
panic("main painc了!")
}
func test() {
defer func() {
if err := recover(); err != nil {
fmt.Printf("err信息是:%+v\n", err)
}
}()
}
胖虎:“……”,这题不会啊,眼看煮熟的鸭子飞跑了,胖虎流下没有技术的泪水。
面试官:不着急,看你的确挺厉害的,给你一次场外求助的机会,读者在评论区留言,在评论区选择出认为对的答案,也算面试成功。
胖虎:“有知道的大佬吗?在线等”
我为大家整理了一些学习资料礼包,关注公众号回复指令:【Golang】、【操作系统】、【Linux】、【LeetCode】、【Golang电子书】即可获得相应学习资料!