go | defer、panic、recover

刷一道题,
将当函数触发panic 之后,函数是怎么执行的

然后我去找相关博客,发现这篇讲的蛮好的

接下来我直接上demo ,然后通过demo 来逐个分析

go 复制代码
package main

import (
	"fmt"
)

func f() {
	defer func() {
		if r := recover(); r != nil {
			fmt.Println("Recover in f", r)
		}
	}()

	fmt.Println("Calling g.")
	g(0)
	fmt.Println("Return normally from g.")
}

func g(i int) {
	if i > 3 {
		fmt.Println("Paninking.....")
		panic(fmt.Sprintf("%v", i))
	}
	defer fmt.Println("Defer in g", i)

	fmt.Println("Printing in g", i)

	g(i + 1)
}

func main() {
	fmt.Println("main start....")
	f()
	fmt.Println("Return normally form f.")

	fmt.Println("main end ....")
}

首先,进入main 协程

打印 main start

接着调用函数f

打印 calling g

调用函数g(0)

进入函数g以后

先打印Printing in g 0

接着调用g(1)

接着打印Printing in g 1

接着调用g(2)

此时打印Printing in g 2

再调用g(3)

此时打印Printing in g 3

调用g(4) 的时候

打印 Paninking...

触发panic 然后把 i= 4 传入panic

Defer in g 3

Defer in g 2

Defer in g 1

Defer in g 0

Recover in f 4

Return normally form f.

main end ...

运行结果

bash 复制代码
go run test_25_panic_recover.go 
main start....
Calling g.
Printing in g 0
Printing in g 1
Printing in g 2
Printing in g 3
Paninking.....
Defer in g 3
Defer in g 2
Defer in g 1
Defer in g 0
Recover in f 4
Return normally form f.
main end ....

上面的分析和运行结果是一致的

接下来分析

bash 复制代码
The panic built-in function stops normal execution of the current goroutine. When a function F calls panic, normal execution of F stops immediately. Any functions whose execution was deferred by F are run in the usual way, and then F returns to its caller. To the caller G, the invocation of F then behaves like a call to panic, terminating G's execution and running any deferred functions. This continues until all functions in the executing goroutine have stopped, in reverse order. At that point, the program is terminated with a non-zero exit code. This termination sequence is called panicking and can be controlled by the built-in function recover.

Starting in Go 1.21, calling panic with a nil interface value or an untyped nil causes a run-time error (a different panic). The GODEBUG setting panicnil=1 disables the run-time error.

这是对panic 函内置函数的定义,翻译(可能有出入,建议有时间慢慢体会)

大致意思是,当前的m函数触发panic 会立即停止,在这之后的defer都不会执行,在这之前的defer都会执行,执行结束跳转至上一层,也就是调用m函数的那一层n,执行该层的defer,这一层的defer执行完毕继续执行调用n函数的这层o 以此类推,直到返回到最开始的f函数,然后这一层会执行defer 然后通过recover获取 panic 错误,上面的返回结果是4

复制代码
painc 内置函数的解释

The recover built-in function allows a program to manage behavior of a panicking goroutine. Executing a call to recover inside a deferred function (but not any function called by it) stops the panicking sequence by restoring normal execution and retrieves the error value passed to the call of panic. If recover is called outside the deferred function it will not stop a panicking sequence. In this case, or when the goroutine is not panicking, or if the argument supplied to panic was nil, recover returns nil. Thus the return value from recover reports whether the goroutine is panicking.

有一个很有意思的东西

比如

func f(){

defer m1

panic m2

defer m3

}

在函数f发生panic ,函数运行随即停止,所以m3部分不会执行,但是m1这部分会执行。接着执行上一层的defer

然后吧啦吧啦

相关推荐
Profile排查笔记10 分钟前
指纹浏览器环境异常排查:Fingerprint、Profile、Proxy、Session 和 Task Log 怎么看
前端·人工智能·后端·自动化
会周易的程序员14 分钟前
microLog 后端开发指南
开发语言·c++·物联网·设计模式·日志·iot·aiot
小强库计算机毕业设计15 分钟前
源码分享Spring Boot + Vue3 的校园社团管理系统
java·spring boot·后端·计算机毕业设计
Esaka_Forever15 分钟前
Python 完整内存管理机制详解
开发语言·python·spring
星空露珠24 分钟前
迷你世界UGc3.0脚本Wiki[剧情动画模块管理接口 Timeline]
开发语言·数据结构·算法·游戏·lua
未来之窗软件服务39 分钟前
计算机考试-C语言 应用题—东方仙盟
c语言·开发语言·仙盟创梦ide·东方仙盟·计算机考试
想你依然心痛40 分钟前
AtomCode在后端开发中的实战体验:Go微服务从零搭建
开发语言·微服务·golang
我是一颗柠檬42 分钟前
【Java项目技术亮点】EXPLAIN深度分析与慢查询治理
android·java·开发语言
luj_17681 小时前
草酸与烟酸对消化及糖代谢的影响解析
服务器·c语言·开发语言·经验分享·算法
阿新聊ai1 小时前
从 Prompt 到 Loop:AI 编程 Agent 四代循环的演进全景
人工智能·后端