Go中panic与recover,从异常中恢复

寅恪光潜
领域专家: 人工智能技术领域
2022-11-16 11:21:01

在go语言中的错误异常,不像其他语言那样try...catch..finally去捕获与控制程序的流程,使用的是多返回值,其中有一个错误的返回,显得特别的简洁,这也是google向来的作风。遇到一些错误的情况,想要恢复如何处理,也就是panic发生错误,然后想使用recover让其恢复。

package main

import "fmt"

func main() {
	recover()
	panic("发生了错误")
	fmt.Println("Hello word!")
}

这种情况发生错误,主程序直接退出,捕获不了错误,recover()放在panic前面和后面都不行。

panic: 发生了错误

goroutine 1 [running]:
main.main()
        C:/Users/Tony/test.go:12 +0x31
exit status 2

这个时候要使用defer,顾名思义,推迟,延期的意思,就是出现了错误,延迟处理的意思。

package main

import "fmt"

func main() {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println(err)
		}
	}()
	panic("发生了错误")
	fmt.Println("Hello word!")
}

C:\Users\Tony>go run test.go
发生了错误

 在defer里面捕获错误之后可以正常执行后面的流程:

defer func() {
		if err := recover(); err != nil {
			fmt.Println(err)
		}
		fmt.Println("AAAA")
	}()

C:\Users\Tony>go run test.go
发生了错误
AAAA

需要注意的是defer需要在panic前面执行,否则recover不会捕获到这个错误:

package main

import "fmt"

func main() {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println(err)
		}
		fmt.Println("AAAA")
	}()
	i := make([]int, 2)
	fmt.Println(i[3])
}

C:\Users\Tony>go run test.go
runtime error: index out of range [3] with length 2
AAAA

 通俗点来说就是panic之后,会走defer这块流程,而不是直接就让程序给崩了。
想深入了解defer和panic可以查看源码:D:\Program Files\Go\src\runtime\runtime2.go,在你的安装目录下面的src目录下面找即可。

type _defer struct {
	started bool
	heap    bool
	// openDefer indicates that this _defer is for a frame with open-coded
	// defers. We have only one defer record for the entire frame (which may
	// currently have 0, 1, or more defers active).
	openDefer bool
	sp        uintptr // sp at time of defer
	pc        uintptr // pc at time of defer
	fn        func()  // can be nil for open-coded defers
	_panic    *_panic // panic that is running defer
	link      *_defer // next defer on G; can point to either heap or stack!

	// If openDefer is true, the fields below record values about the stack
	// frame and associated function that has the open-coded defer(s). sp
	// above will be the sp for the frame, and pc will be address of the
	// deferreturn call in the function.
	fd   unsafe.Pointer // funcdata for the function associated with the frame
	varp uintptr        // value of varp for the stack frame
	// framepc is the current pc associated with the stack frame. Together,
	// with sp above (which is the sp associated with the stack frame),
	// framepc/sp can be used as pc/sp pair to continue a stack trace via
	// gentraceback().
	framepc uintptr
}

type _panic struct {
	argp      unsafe.Pointer // pointer to arguments of deferred call run during panic; cannot move - known to liblink
	arg       any            // argument to panic
	link      *_panic        // link to earlier panic
	pc        uintptr        // where to return to in runtime if this panic is bypassed
	sp        unsafe.Pointer // where to return to in runtime if this panic is bypassed
	recovered bool           // whether this panic is over
	aborted   bool           // the panic was aborted
	goexit    bool
}

recover怎么恢复的实现可以查看源码:D:\Program Files\Go\src\runtime\panic.go
当然这些属于底层的东西,有兴趣的可以去熟悉。
欢迎加入我们,一起学习一起进步,有什么疑问尽管问!

...全文
153 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
CSDN-Ada助手 2023-01-13
  • 打赏
  • 举报
回复
您可以前往 CSDN问答-编程语言 发布问题, 以便更快地解决您的疑问

199

社区成员

发帖
与我相关
我的任务
社区描述
从零开始的小白到进阶成技术达人。 一起学习,一起进步。
golanggo1.19 个人社区 贵州省·贵阳市
社区管理员
  • 寅恪光潜
  • 网络豆
  • Somnus_小凯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

Go语言集各语言优势之大成,从基础到进阶

一起学习,一起进步,成为技术达人!

试试用AI创作助手写篇文章吧