前言
本文将以我自己的学习了解的,和在工作中遇到的panic为基础;记录我遇到的panic情况,以及合适的处理方法。本文是个人的经验记录,不是专业的panic机制教学,因此严谨性和准确性不是本文的首要目标,我将以更工作视角和个人视角来阐述我对panic的理解以及配套的解决方案。
panic是什么
这个问题我抛给AI,AI给我的答案是“运行时异常机制”,即用于处理程序无法正常继续执行的 “不可恢复错误”。这里的既然有无法正常继续执行无法恢复的错误,那肯定也有普通的错误,我称之为业务错误。
那么二者有什么区别呢?我的理解是,业务错误是可以预见的错误,我们在写Go代码时,往往会在调用函数和方法后搞一个 if err != nil,随后对err进行处理。这就是一种可以预见的错误,比如:
if data, err = DescribeDatas(id); err != nil {
log.Errof("DescribeDatas出现错误")
return xx,err
}
这是一个Go代码中最最最最最常见的错误处理,DescribeDatas去数据库里查询数据,如果出现了错误,那么就会直接执行if条件中的代码。很显然,这里的错误是可以预见的,当出现这种业务错误时,程序是感知不到所谓错误的概念,这是一种业务层面对错误的显示处理。
但是如果出现下面这种情况,就大不相同:
func func1(data1 int) *int {
// 某种情况希望返回空的指针变量
if (someSituation) {
return nil
}
return xxx
}
func func2() {
a := func1(xxx);
// 一些正常逻辑
*a;
}
可以看到,func1返回的是一个指针,这里虽然是int类型,但实际企业代码中很有可能是一个复杂的结构体指针,甚至是结构体内部的某个指针变量。同时该代码中存在一个非常少见的if,会返回nil。而另外一个很远的地方可能存在某个调用这个函数的地方,并对结果进行解引用。那么这个时候程序可能就会出现解引用空指针的panic,在微服务架构中,某个pod可能就会偷偷重启。哪怕这个if里的条件极小的概率发生,但是在用户足够多的情况下,它就会必然发生,最后导致业务价值的损失。
这种情况就是panic,程序没有预料到这种错误,会导致服务的重启。在K8S的管理下pod会重启对业务的影响可能不是很大,但在单体架构中服务的崩溃可能会十分致命(虽然这种情况一般只发生在个人开发者的业务中)。
工作中遇到的panic
文章这之后我将总结我在工作中遇到的panic,不定时更新。
数据库映射+断言panic
to be added