You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
|
|
**panic 是基于goroutine级别的异常机制**,即是说,如果你程序里的 `panic` 的产生跨多个 `goroutine` 时,那么此时你想 `catch` 住该 `panic` ,一定在 `panic` 产生的同一个 `goroutine` 里进行捕获,否则无效。
|
|
|
|
|
|
|
|
|
|
同一个`goroutine` javaer可以理解为同一个线程内
|
|
|
|
|
|
|
|
|
|
# 一、简单使用
|
|
|
|
|
## 1.1 同一个goroutine
|
|
|
|
|
![[Pasted image 20231202224619.png]]
|
|
|
|
|
|
|
|
|
|
## 1.2 跨goroutine
|
|
|
|
|
![[Pasted image 20231202224733.png]]
|
|
|
|
|
调用链关系未变,但 `func2`、`func3` 在不同的 `goroutine` 中,那么这时候在 `func1` 中是无法捕获到后续子协程的 `panic` 异常,**而且,这种子协程的 `panic` 如果未有效拦截,也会导致主进程崩溃,所以不得不重视它。**
|
|
|
|
|
所以,但凡你要新启一个 `goroutine`,而你又不完全确定是否它会产生 `panic` ,那么保险的做法在启动的时候进行拦截,做到 "谁创建,谁负责" 的原则。
|
|
|
|
|
|
|
|
|
|
![[Pasted image 20231202224859.png]]
|
|
|
|
|
|
|
|
|
|
# 二、panic和直接返回error
|
|
|
|
|
这个问题有不少争论,估计go2官方会出新的异常处理语法,先来对比下两种方式:
|
|
|
|
|
+ error
|
|
|
|
|
```go
|
|
|
|
|
// 使用error的写法
|
|
|
|
|
func first() error {return nil}
|
|
|
|
|
func second() error {return nil}
|
|
|
|
|
func third() error {return nil}
|
|
|
|
|
func fourth() error {return nil}
|
|
|
|
|
func fifth() error {return nil}
|
|
|
|
|
|
|
|
|
|
func Do() error {
|
|
|
|
|
var err error
|
|
|
|
|
if err = first(); err == nil {
|
|
|
|
|
if err = second(); err == nil {
|
|
|
|
|
if err = third(); err == nil {
|
|
|
|
|
if err = fourth(); err == nil {
|
|
|
|
|
if err = fifth(); err == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
+ panic
|
|
|
|
|
```go
|
|
|
|
|
// panic 写法
|
|
|
|
|
func Do2() (err error) {
|
|
|
|
|
defer func(){
|
|
|
|
|
if r:= recover() ; r!= nil{
|
|
|
|
|
err = fmt.Errorf("Error: %+v", r)
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
first2()
|
|
|
|
|
second2()
|
|
|
|
|
third2()
|
|
|
|
|
fourth2()
|
|
|
|
|
fifth2()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
存在多层次的调用,问题在于如何准确定位异常位置,目前go没有好的解决办法。
|