2、go 异常处理 recover

12 阅读1分钟

无效用法

1、pnic在前不会往下执行

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

2、f2()在方法中已经执行完recover了,不会影响到case2中的panic

func case2() {
    f2()
    panic("panic")
}

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

3、

over() 只有在当前 正在执行的 defer 函数内部直接调用时才有效。 在 f2() 中注册的 defer func(){...}() 是在 f2() 被调用时压入 defer 栈的。 当 case2() 中发生 panic 时,Go 开始执行已注册的 defer 函数(即 f2())。 此时再调用 f2(),又注册一个新的 defer(即 func(){ recover() }),但此时已经 在 panic 流程中了,新注>册的 defer 已经来不及触发 recover()。 简单理解:recover() 必须出现在 panic 触发前就已经注册好的 defer 函数中。 如果 recover() 是在 panic 发生之后,通过 defer 函数再注册 defer,那它就无法捕获到 panic。

func case2() {
   defer func() {
      f2()
   }()
   panic("panic")
}

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

4、 没有执行返回的func

func case2() {
    defer f3()
    panic("panic")
}


func f3() func() {
    return func() {
       err := recover()
       if err != nil {
          fmt.Println(err)
       }
    }
}

有效用法

1、先把recover注册进入defer中

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

2、:立即调用返回的闭包函数,并在其内部执行 recover() 来捕获 panic

func case2() {
    defer f3()()
    panic("panic")
}

func f3() func() {
    return func() {
       err := recover()
       if err != nil {
          fmt.Println(err)
       }
    }
}