美文网首页
go 的异常处理:panic 和 recover

go 的异常处理:panic 和 recover

作者: wayyyy | 来源:发表于2021-12-12 03:27 被阅读0次
panic 函数 和 recover 函数

panicrecover 在使用方法上更接近于 try/catch 结构化异常:

func panic(v interface{})
func recover() interface{}
defer panic recover 执行顺序
  • go 中协程是平等的,如果一个协程中产生的 panic 没有处理掉,会导致整个程序奔溃

    package main
    
    func main() {
      go func() {
          panic("hello world")
      }()
    
      select {}
    }
    
    image.png
  • panic 会递归的执行本协程中所有的defer,与函数正常退出时执行的顺序一致

    func main() {
        defer fmt.Print("A")
        defer fmt.Print("B")
        fmt.Print("C")
        panic("demo")
        defer fmt.Print("D")
    }
    
    image.png
  • panic 不会调用其他协程中的defer

    func foo() {
        defer fmt.Print("A")
        defer fmt.Print("B")
        
        fmt.Print("C")
        panic("foo demo")
        defer fmt.Print("D")
    }
    
    func main() {
        defer func () {  fmt.Print("main demo")  }()
        go foo()
        select {}  // 防止main协程提前退出
    }
    
    image.png
  • 如果panic在执行过程再次发生panic,程序立即终止当前的 defer函数的执行,然后继续接下来的panic流程,只是当前的defer函数中的panic后面的语句就没有机会执行了

    func main() {
        defer func() { recover() }()
    
        defer fmt.Println("A")
        defer func() {
            fmt.Print("B")
            panic("panic in defer")
            fmt.Print("C")
        }()
    
        panic("panic")
        fmt.Print("D")
    }
    
    image.png

    注意 C 没有输出。

  • 当函数中发生panic 并用 recover 恢复后,无法回到本函数发生panic的位置继续执行

    func foo() {
        defer fmt.Println("C")
        defer func() {
            if err := recover(); err != nil {
                fmt.Print("A")
            }
        }()
    
      panic("demo")
      fmt.Println("B")
    }
    
    func main() {
        foo()
    }
    
    image.png

    注意没有输出B

  • panic 被 recover 之后,无法再次被 recover 捕获

    func foo() {
        defer func() {
            if err := recover(); err != nil {
                fmt.Print("A")
            }
            fmt.Print("a")
        }()
    
        defer func() {
            if err := recover(); err != nil {
                fmt.Print("B")
            }
        }()
    
        panic("demo")
        fmt.Print("B")
    }
    
    func main() {
        foo()
    }
    
    image.png
  • recover 函数必须且直接位于defer函数中才有效
    func main() {
        defer func() {
            func() {
                if err := recover(); err != nil {
                    fmt.Println("A")
                }
            }()
        }()
    
        panic("demo")
        fmt.Println("B")
    }
    

    上面这种写法就不会生效。


    image.png

相关文章

网友评论

      本文标题:go 的异常处理:panic 和 recover

      本文链接:https://www.haomeiwen.com/subject/obbutrtx.html