9.8Go之函数之宕机恢复(recover)
recover的概念
- 
Recover 是一个Go语言的内建函数,可以让进入宕机流程中的 goroutine 恢复过来 
特点:
- 
recover 仅在延迟函数 defer 中有效,在正常的执行过程中,调用 recover 会返回 nil 并且没有其他任何效果 
- 
如果当前goroutine发生异常,调用recover可以捕获panic的输入值,且恢复正常的执行 
Go语言没有异常系统,其使用 panic 触发宕机类似于其他语言的抛出异常,recover 的宕机恢复机制就对应其他语言中的 try/catch 机制。--->非常重要
panic和recover之间的关系
- 
有 panic 没 recover,程序宕机。 
- 
有 panic 也有 recover,程序不会宕机,执行完对应的 defer 后,从宕机点退出当前函数后继续执行。 
其他语言的异常处理机制的目的
以Java中的异常处理机制为例:
- 
底层抛出异常,上层逻辑通过 try/catch 机制捕获异常 
- 
没有被捕获的严重异常会导致宕机,捕获的异常可以被忽略,让代码继续运行。 
本质就是希望通过捕获异常的方式让程序继续运行下去
让程序在崩溃时继续运行示例
需求:
- 
实现一个Run函数 - 
传入一个匿名函数或闭包后的执行函数--->形参 
 
- 
- 
传入函数以任何形式发生 panic 崩溃后,可以将崩溃发生的错误打印出来 
- 
同时允许后面的代码继续运行,不会造成整个进程的崩溃。 
package main
import (
    "fmt"
    "runtime"
)
/*
定义一个结构体,里面的元素定义为抛出异常时需要传递的上下文信息
 */
type panicContent struct {
    function string //当前所在函数
}
/*
声明描述错误的结构体,保存执行错误的函数。
 */
/*
实现一个run函数,形参为一个函数或者是闭包
 */
func Run(entry func()) {
    //defer标记宕机处理
    defer func() { //--->非常重要:defer 将闭包延迟执行,当 panic 触发崩溃时,Run() 函数将结束运行,此时 defer 后的闭包将会发生调用
        //发生宕机时,获取panic传递的上下文并打印
        err := recover() //recover() 获取到 panic 传入的参数
        switch err.(type) { //错误类型断言
        case runtime.Error:
            //运行时异常
            fmt.Println("runtime Error:", err)
        default:
            fmt.Println("another unknow Error:", err)
        }
    }()
    entry()
}
func main() {
    fmt.Println("运行前:")
    //调用run函数,手动触发错误
    Run(func() {
        fmt.Println("手动触发宕机前:")
        //使用panic结构体传递上下文--->一个指针对象,指向结构体
        panic(&panicContent{ //--->这是将一个结构体附带信息传递给panic
            "手动触发panic",
            /*
            使用 panic 手动触发一个错误,并将一个结构体附带信息传递过去
            recover 就会获取到这个结构体信息,并打印出来
             */
        })
        fmt.Println("手动触发宕机后。")
    })
    /*
    这不是一个运行时异常,宕机被恢复了,所以可以执行下面一个空指针错误的方法
     */
    //手动触发空指针错误
    Run(func() {
        fmt.Println("赋值宕机前:")
        var a *int
        *a = 1 
                     
                    
                 
                    
                