• golang - recover 使用笔记



    作用:程序报panic时,会使整个程序挂掉,在实际工作中,报panic的地方可能会非常的多,一旦报panic会导致整个服务挂掉,是非常危险的。golang 引用recover()函数来捕获异常,使得即使报panic,也能继续运行下去。

     通常写法:

    1. defer func() {
    2.         if err := recover(); err !=nil {
    3.             fmt.Println(err)
    4.         }
    5.     }()


    作用域:

    1. recover() 只是针对当前函数和以及直接调用的函数可能产生的panic
    2. 它无法处理其调用产生的其它协程的panic


     举例说明:

          1.下面程序,一旦运行test2() 函数会导致panic,程序会立即挂掉

    1. package main
    2.  
    3. import (
    4.     "fmt"
    5. )
    6.  
    7.  
    8. func main() {
    9.     test1()       //输出:this is test 1
    10.     test2()       //输出:this is test 2  panic: test 2 is panic   直接挂掉
    11.     test3()                 
    12. }
    13.  
    14. func test1 (){
    15.     fmt.Println("this is test 1")
    16. }
    17.  
    18. func test2 (){
    19.     fmt.Println("this is test 2")
    20.     panic("test 2 is panic")
    21. }
    22.  
    23. func test3 (){
    24.     fmt.Println("this is test 3")
    25. }


     
     
         2. 当我们在test2() 函数加入recover()时,程序运行到test2()函数,报panic 错误不会挂掉,程序会继续进行,执行test()3函数。

    1. package main
    2.  
    3. import (
    4.     "fmt"
    5. )
    6.  
    7.  
    8. func main() {
    9.     test1()   //输出:this is test 1
    10.     test2()   //输出:this is test 2  test 2 is  panic
    11.     test3()   //输出:this is test 3
    12. }
    13.  
    14. func test1 (){
    15.     fmt.Println("this is test 1")
    16. }
    17.  
    18. func test2 (){
    19.     defer func() {
    20.         if err := recover(); err !=nil {
    21.             fmt.Println(err)
    22.         }
    23.     }()
    24.     fmt.Println("this is test 2")
    25.     panic("test 2 is panic")
    26. }
    27.  
    28. func test3 (){
    29.     fmt.Println("this is test 3")
    30. }


     
     
           3.当我们把 recover() 放在 直接调用的test2()的main 函数之中时,当程序执行到test2函数时,报panic 这时test2()程序中断,程序不会往下执行,而是直接执行defer 中的recover()函数(同时说明,即使程序某个位置报了panic错误,最后也会执行defer),整个程序不会挂掉。

    1. package main
    2.  
    3. import (
    4.     "fmt"
    5. )
    6.  
    7.  
    8. func main() {
    9.     defer func() {
    10.         if err := recover(); err !=nil {
    11.             fmt.Println(err)
    12.         }
    13.     }()
    14.     test1()    //输出: this is test 1
    15.     test2()    //输出: this is test 2; test 2 is panic
    16.     test3()    //不会执行
    17. }
    18.  
    19. func test1 (){
    20.     fmt.Println("this is test 1")
    21. }
    22.  
    23. func test2 (){
    24.     fmt.Println("this is test 2")
    25.     panic("test 2 is panic")
    26. }
    27.  
    28. func test3 (){
    29.     fmt.Println("this is test 3")
    30. }


     
     
        4. 当为test2()开了个go 协程时,程序依然会报panic 导致整个程序挂掉。

    1. package main
    2.  
    3. import (
    4.     "fmt"
    5. )
    6.  
    7.  
    8. func main() {
    9.  
    10.     defer func() {
    11.         if err := recover(); err !=nil {
    12.             fmt.Println(err)
    13.         }
    14.     }()
    15.     
    16.     test1()
    17.     go test2()
    18.     test3()
    19.     for {
    20.         select {
    21.  
    22.         }
    23.     }
    24. }
    25.  
    26. func test1 (){
    27.     fmt.Println("this is test 1")
    28. }
    29.  
    30. func test2 (){
    31.     fmt.Println("this is test 2")
    32.     panic("test 2 is panic")
    33. }
    34.  
    35. func test3 (){
    36.     fmt.Println("this is test 3")
    37. }


     
     
      5. 当为test2()开了个协程时,正确的做法是 在recove(),放在test2()里面才不会导致整个程序挂掉。

    1. package main
    2.  
    3. import (
    4.     "fmt"
    5. )
    6.  
    7.  
    8. func main() {
    9.  
    10.     test1()     // 输出:this is test 1
    11.     go test2()  //  this is test 2; test 2 is panic
    12.     test3()     //this is test3
    13.     for {        //不推荐这样写 会造成死锁  此处只是单单为了 演示
    14.         select {
    15.  
    16.         }
    17.     }
    18. }
    19.  
    20. func test1 (){
    21.     fmt.Println("this is test 1")
    22. }
    23.  
    24. func test2 (){
    25.     defer func() {
    26.         if err := recover(); err !=nil {
    27.             fmt.Println(err)
    28.         }
    29.     }()
    30.     fmt.Println("this is test 2")
    31.     panic("test 2 is panic")
    32. }
    33.  
    34. func test3 (){
    35.     fmt.Println("this is test 3")
    36. }


     
    //输出结果:

    1. // this is test 1
    2. // this is test 3
    3. // this is test 2
    4. // test is panic  


     

  • 相关阅读:
    Denodo通过重要任命新增执行团队成员:Daniel Lender担任首席财务官,Stephen Welles担任首席法务官
    13. Spring AOP(一)思想及使用
    一百九十一、Flume——Flume配置文件各参数含义(持续完善中)
    下一代智能合约编程语言Move(二)
    数据结构之赫曼夫树(哈曼夫树)
    5.23 BCC工具之drsnoop.py解读
    快速搭建SpringBoot3.x项目
    WebSocket原理简介
    OrangePi Kunpeng Pro 开发板测评 | AI 边缘计算 & 大模型部署
    【红帽】跟着学习如何使用桌面访问命令行
  • 原文地址:https://blog.csdn.net/xuezhangjun0121/article/details/132762344