zhcn 编程语言 Golang Golang 容器 非公開: Go语言宕机恢复(recovery)——防止程序崩溃

Go语言宕机恢复(recovery)——防止程序崩溃

Recover是Go语言中的一个内置函数,允许您在停机过程中恢复goroutine。仅当使用 defer 函数 defer 时,recover 才有效。在正常执行期间,调用recover会返回nil并且没有其他效果。如果当前的goroutine情况处于panic状态,可以调用recover来捕获panic输入值并恢复正常执行。

一般来说,您不应该对陷入严重停机的程序执行任何操作,但在某些情况下您可能需要从停机中恢复。例如,如果 Web 服务器遇到重大意外问题,它必须在崩溃之前关闭所有连接。如果您什么都不做,客户端将处于等待状态。如果Web服务器还处于开发阶段,服务器还可以将异常信息反馈给Web服务器。客户端对于调试很有用。

尖端

在其他语言中,停机通常以异常的形式存在。底层抛出异常,上层逻辑通过try/catch机制捕获异常。未捕获的严重异常会导致停机。捕获的异常可以被忽略,代码继续执行。执行。

Go语言没有异常系统。使用panic来触发停机类似于在其他语言中抛出异常。其中recover宕机恢复机制对应其他语言中的try/catch机制。

允许程序继续运行,即使它崩溃了

以下代码实现 ProtectRun() 函数。该函数在闭包后传递一个匿名函数或执行函数。如果您的接收函数以任何方式发生恐慌,您可以打印崩溃错误并允许后续代码。代码继续运行没有问题。整个过程崩溃了。

保护正在运行的功能。

 package main

import (
    "fmt"
    "runtime"
)

// パニック時に渡すコンテキスト情報
type panicContext struct {
    function string // 関数名
}

// 保護された方法で関数を実行する
func ProtectRun(entry func()){

    // 遅延処理関数
   defer func(){

        // パニックで渡されたコンテキストを取得して出力
       error:= recover()

        switch err.(type){
        case runtime.Error:// 実行時エラー
            fmt.Println("runtime error:", err)
        default:// 実行時エラー以外
            fmt.Println("error:", err)
        }

    }()

   entry()

}

func main(){
    fmt.Println("動作前")

    // 手動エラーの実行を許可
    ProtectRun(func() {

        fmt.Println("手動パニックの前")

        // パニックでコンテキストを渡す
        panic(&panicContext {
            "手動によるパニックの発生",
        })

        fmt.Println("手動パニックの後")
    })

    // ヌルポインターアクセスのエラーを意図的に引き起こす
    ProtectRun(func() {

        fmt.Println("割り当てパニックの前")

        var a *int
        *a = 1

        fmt.Println("割り当てパニックの後")
    })

    fmt.Println("実行後")
} 

代码输出结果:

動作前
手動パニックの前
手動によるパニックの発生
割り当てパニックの前
runtime error: runtime error: invalid memory address or nil pointer dereference
実行後

代码解释:

  • 第 9 行声明了一个结构体,用于描述错误并存储执行错误的函数。
  • 第 17 行使用 defer 来推迟闭包的执行。如果恐慌导致崩溃,则 ProtectRun() 函数将完成执行并在调用 defer 后关闭。
  • 第20行,recover()获取panic传递的参数。
  • 第 22 行使用 switch 对 err 变量执行类型断言。
  • 如果错误是运行时层抛出的运行时错误,例如空指针访问或除数为 0,则第 23 行将打印运行时错误。
  • 第 25 行的另一个错误打印了传递的错误数据。
  • 在第 44 行,使用恐慌手动触发错误并传递包含该信息的结构。此时,recover 检索并输出结构信息。
  • 第57行,模拟代码中空指针分配引起的错误被运行时层抛出,并被ProtectRun()函数的cover()函数捕获。

恐慌与恢复之间的关系

恐慌与恢复的结合具有以下特点:

  • 发生恐慌,但无法恢复,程序崩溃。
  • 恐慌和恢复随之而来。程序就不会下去了。执行相应的延迟后,从停机点退出当前函数并继续执行。

尖端

虽然panic/recovery可以模拟其他语言中的异常机制,但不建议在编写常规函数时频繁使用该功能。

由panic触发的defer函数可以不断调用panic并抛出更多错误,直到整个程序崩溃。

如果要在捕获错误时设置当前函数的返回值,可以使用命名返回值方法直接设置返回值。

《Go语言宕机恢复(recovery)——防止程序崩溃》浅显易懂讲解!您必须观看的最佳 2 个视频

【たった1時間で学べる】Go言語のプログラミング初心者向けの超入門講座【文字書き起こし、ソースコードも完全無料!】
https://www.youtube.com/watch?v=kPXfMFJ0oIE&pp=ygVqIEdvIOiogOiqnuOBruODgOOCpuODs-OCv-OCpOODoOWbnuW- qSAo5Zue5b6pKSAtIOODl-ODreOCsOODqeODoOOBruOCr-ODqeODg-OCt-ODpeOCkumYsuatouOBl-OBvuOBmSZobD1KQQ%3D%3D
【Go言語 超入門コース】14.メソッド|Goのメソッドは、他の言語のメソッドとは違っています【プログラミング初心者向け入門講座】
https://www.youtube.com/watch?v=D4tEBHbuOos&pp=ygVqIEdvIOiogOiqnuOBruODgOOCpuODs-OCv-OCpOODoOWbnuW- qSAo5Zue5b6pKSAtIOODl-ODreOCsOODqeODoOOBruOCr-ODqeODg-OCt-ODpeOCkumYsuatouOBl-OBvuOBmSZobD1KQQ%3D%3D
Recover是Go语言中的一个内置函数,允许您在停机过程中恢复goroutine。仅当使用 defer 函数 defer 时,recover 才有效。在正常执行期间,调用recover会返回nil并且没有其他效果。如果当前的goroutine情况处于panic状态,可以调用recover来捕获panic输入值并恢复正常执行。

一般来说,您不应该对陷入严重停机的程序执行任何操作,但在某些情况下您可能需要从停机中恢复。例如,如果 Web 服务器遇到重大意外问题,它必须在崩溃之前关闭所有连接。如果您什么都不做,客户端将处于等待状态。如果Web服务器还处于开发阶段,服务器还可以将异常信息反馈给Web服务器。客户端对于调试很有用。

尖端

在其他语言中,停机通常以异常的形式存在。底层抛出异常,上层逻辑通过try/catch机制捕获异常。未捕获的严重异常会导致停机。捕获的异常可以被忽略,代码继续执行。执行。

Go语言没有异常系统。使用panic来触发停机类似于在其他语言中抛出异常。其中recover宕机恢复机制对应其他语言中的try/catch机制。

允许程序继续运行,即使它崩溃了

以下代码实现 ProtectRun() 函数。该函数在闭包后传递一个匿名函数或执行函数。如果您的接收函数以任何方式发生恐慌,您可以打印崩溃错误并允许后续代码。代码继续运行没有问题。整个过程崩溃了。

保护正在运行的功能。

 package main

import (
    "fmt"
    "runtime"
)

// パニック時に渡すコンテキスト情報
type panicContext struct {
    function string // 関数名
}

// 保護された方法で関数を実行する
func ProtectRun(entry func()){

    // 遅延処理関数
   defer func(){

        // パニックで渡されたコンテキストを取得して出力
       error:= recover()

        switch err.(type){
        case runtime.Error:// 実行時エラー
            fmt.Println("runtime error:", err)
        default:// 実行時エラー以外
            fmt.Println("error:", err)
        }

    }()

   entry()

}

func main(){
    fmt.Println("動作前")

    // 手動エラーの実行を許可
    ProtectRun(func() {

        fmt.Println("手動パニックの前")

        // パニックでコンテキストを渡す
        panic(&panicContext {
            "手動によるパニックの発生",
        })

        fmt.Println("手動パニックの後")
    })

    // ヌルポインターアクセスのエラーを意図的に引き起こす
    ProtectRun(func() {

        fmt.Println("割り当てパニックの前")

        var a *int
        *a = 1

        fmt.Println("割り当てパニックの後")
    })

    fmt.Println("実行後")
} 

代码输出结果:

動作前
手動パニックの前
手動によるパニックの発生
割り当てパニックの前
runtime error: runtime error: invalid memory address or nil pointer dereference
実行後

代码解释:

  • 第 9 行声明了一个结构体,用于描述错误并存储执行错误的函数。
  • 第 17 行使用 defer 来推迟闭包的执行。如果恐慌导致崩溃,则 ProtectRun() 函数将完成执行并在调用 defer 后关闭。
  • 第20行,recover()获取panic传递的参数。
  • 第 22 行使用 switch 对 err 变量执行类型断言。
  • 如果错误是运行时层抛出的运行时错误,例如空指针访问或除数为 0,则第 23 行将打印运行时错误。
  • 第 25 行的另一个错误打印了传递的错误数据。
  • 在第 44 行,使用恐慌手动触发错误并传递包含该信息的结构。此时,recover 检索并输出结构信息。
  • 第57行,模拟代码中空指针分配引起的错误被运行时层抛出,并被ProtectRun()函数的cover()函数捕获。

恐慌与恢复之间的关系

恐慌与恢复的结合具有以下特点:

  • 发生恐慌,但无法恢复,程序崩溃。
  • 恐慌和恢复随之而来。程序就不会下去了。执行相应的延迟后,从停机点退出当前函数并继续执行。

尖端

虽然panic/recovery可以模拟其他语言中的异常机制,但不建议在编写常规函数时频繁使用该功能。

由panic触发的defer函数可以不断调用panic并抛出更多错误,直到整个程序崩溃。

如果要在捕获错误时设置当前函数的返回值,可以使用命名返回值方法直接设置返回值。

《Go语言宕机恢复(recovery)——防止程序崩溃》浅显易懂讲解!您必须观看的最佳 2 个视频

【たった1時間で学べる】Go言語のプログラミング初心者向けの超入門講座【文字書き起こし、ソースコードも完全無料!】
https://www.youtube.com/watch?v=kPXfMFJ0oIE&pp=ygVqIEdvIOiogOiqnuOBruODgOOCpuODs-OCv-OCpOODoOWbnuW- qSAo5Zue5b6pKSAtIOODl-ODreOCsOODqeODoOOBruOCr-ODqeODg-OCt-ODpeOCkumYsuatouOBl-OBvuOBmSZobD1KQQ%3D%3D
【Go言語 超入門コース】14.メソッド|Goのメソッドは、他の言語のメソッドとは違っています【プログラミング初心者向け入門講座】
https://www.youtube.com/watch?v=D4tEBHbuOos&pp=ygVqIEdvIOiogOiqnuOBruODgOOCpuODs-OCv-OCpOODoOWbnuW- qSAo5Zue5b6pKSAtIOODl-ODreOCsOODqeODoOOBruOCr-ODqeODg-OCt-ODpeOCkumYsuatouOBl-OBvuOBmSZobD1KQQ%3D%3D