**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没有好的解决办法。