zoukankan      html  css  js  c++  java
  • 9.8Go之函数之宕机恢复(recover)

    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
    /*
    模拟代码中空指针赋值造成的错误
    由 Runtime 层抛出错误,被 Run() 函数的 recover() 函数捕获到
    */

    fmt.Println("赋值宕机后。")
    })
    /*
    这是一个运行时异常
    */

    fmt.Println("运行后。")
    }

    代码分析:

    • defer标记的函数--->panic触发崩溃run函数即将结束才会执行

    • panic--->可以将一个结构体传递给panic,通过指针传递,并且附带内容。panic获取到以后直接会打印里面的内容

    • 空指针错误被抛出会在run函数结束前由recover函数捕获到然后让程序继续往下执行--->不会退出

  • 相关阅读:
    我的Java学习路线图
    请求重定向和请求转发的区别
    PHP代码审计学习-php安全基础
    无密码正向直连内网linux目标机复现
    Windows API 学习
    Http请求走私
    免杀手法-tcp套字节传递shellcode学习
    自启动模块构造-计划任务
    自启动模块构造-快速启动目录
    进程注入免杀学习
  • 原文地址:https://www.cnblogs.com/JunkingBoy/p/15244307.html
Copyright © 2011-2022 走看看