最近学习到go语言的反射机制,在这里经常需要对异常处理,久而久之便对其中最近常出现的panic这个异常产生了兴趣,在go语言中可以算是一种常见的异常报错
在编辑的时候是一种常见的错误
go语言的类型系统会在编辑时进行错误的捕获,但panic异常更多不是在编辑时报错,而是在运行时被检查出来,比如数组越界访问,空指针的引用等都有可能会导致终端报panic这个错误
在报完panic 这个异常之后程序会中断运行,同时开始执行改goroutine中延迟的函数(比如defer函数等)随后程序退出并且留下日志
那么我们可以通过日志进行错误地址的判断
但要注意并不是所有的问题都来自运行时,也有可能是人为调用panic函数导致panic异常的,因为panic这个函数接收任何值作为参数,所以在发生了什么不该发生的问题或者对问题有预测的情况下我们应该进行调用panic函数进行程序的终止
比如程序出现了不可能走向的那条路线,这时需要对其进行终止
但要注意,panic引起的程序终止和一般情况下的程序终止是不一样的,这里的终止可以理解成为程序面临崩溃,比如说内容的程序逻辑不一致,所以在大多数情况下应该使用 Go 提供的错误机制,而不是 panic,尽量避免程序的崩溃。在健壮的程序中,任何可以预料到的错误,如不正确的输入、错误的配置或是失败的 I/O 操作都应该被优雅的处理,最好的处理方式,就是使用 Go 的错误机制。
Recover 捕获异常
我们可以从异常中恢复,至少我们可以在程序崩溃前,做一些操作。
举个例子,当 web 服务器遇到不可预料的严重问题时,在崩溃前应该将所有的连接关闭;如果不做任何处理,会使得客户端一直处于等待状态。如果 web 服务器还在开发阶段,服务器甚至可以将异常信息反馈到客户端,帮助调试。
如果在 deferred 函数中调用了内置函数 recover,并且定义该 defer 语句的函数发生了 panic 异常,recover 会使程序从 panic 中恢复,并返回 panic value。导致 panic 异常的函数不会继续运行,但能正常返回。在未发生 panic 时调用 recover,recover 会返回 nil。
deferred 函数帮助 Parse 从 panic 中恢复。在 deferred 函数内部,panic value 被附加到错误信息中;并用 err 变量接收错误信息,返回给调用者。我们也可以通过调用 runtime.Stack 往错误信息中添加完整的堆栈调用信息