Go defer、panic 和 recover

在 Go 中,我们使用 defer、panic 和 recover 语句来处理错误。

我们使用 defer 来延迟可能导致错误的函数的执行。panic 语句会立即终止程序,而 recover 用于在 panic 期间恢复消息。

在学习错误处理语句之前,请确保了解 Go 错误


defer in Go

我们使用 defer 语句来阻止一个函数的执行,直到所有其他函数执行完毕。例如,

package main
import "fmt"

func main() {

// defer the execution of Println() function defer fmt.Println("Three")
fmt.Println("One") fmt.Println("Two") }

输出

One
Two
Three

在上面的示例中,我们在第一个打印语句之前使用了 defer。

因此,Println() 函数在所有其他函数执行完毕后最后执行。


Multiple defer Statements in Go

当我们在程序中使用多个 defer 时,defer 语句的执行顺序将是 **LIFO(后进先出)**。

这意味着最后一个 defer 语句将首先执行。例如,

package main
import "fmt"

func main() {

defer fmt.Println("One") defer fmt.Println("Two") defer fmt.Println("Three")
}

输出

Three
Two
One

在上面的示例中,我们使用 3 个 defer 语句来调用 Println() 函数。

正如你所见,执行顺序是 **LIFO**。也就是说,最后一个 defer 语句首先执行,第一个 defer 语句最后执行。


Golang panic

我们使用 panic 语句立即结束程序的执行。如果我们的程序到达一个点,由于某些严重错误而无法恢复,最好使用 panic。

panic 语句之后的代码行不会被执行。例如,

package main
import "fmt"

func main() {

  fmt.Println("Help! Something bad is happening.")
panic ("Ending the program")
fmt.Println("Waiting to execute") }

输出

Help! Something bad is happening.
panic: Ending the program

在这里,程序在到达 panic 语句时终止。这就是为什么 panic 之后的打印语句没有被执行。

注意: 输出中的 panic: 表明程序因 panic 而终止,并且它是 panic 消息。


Example: Panic in Golang

package main

import "fmt"

func division(num1, num2 int) {

// if num2 is 0, program is terminated due to panic if num2 == 0 { panic("Cannot divide a number by zero")
} else { result := num1 / num2 fmt.Println("Result: ", result) } } func main() { division(4, 2) division(8, 0) division(2, 8) }

输出

Result:  2
panic: Cannot divide a number by zero

在上面的示例中,我们创建了一个执行两个数相除的函数:num1num2

在函数内部,我们使用了一个 if...else 语句 来检查 num2(分母)是否为 **0**。如果是 **0**,程序将因 **panic 语句** 而停止执行。

panic("Cannot divide a number by zero")

在这里,当我们运行程序时,我们首先得到结果 **2**(4 除以 2)。然而,在第二次函数调用期间,num2 的值为 **0**(8 除以 0)。

因此,程序被终止。


recover in Go Programming

panic 语句会立即终止程序。但是,有时程序完成执行并获得一些所需结果可能很重要。

在这些情况下,我们使用 recover 语句来处理 Go 中的 panic。**recover 语句** 会阻止程序终止,并使程序从 panic 中恢复。

让我们看一个例子。

package main
import "fmt"

// recover function to handle panic
func handlePanic() {

  // detect if panic occurs or not
  a := recover()

  if a != nil {
    fmt.Println("RECOVER", a)
  }

}

func division(num1, num2 int) {

  // execute the handlePanic even after panic occurs
  defer handlePanic()

  // if num2 is 0, program is terminated due to panic
  if num2 == 0 {
    panic("Cannot divide a number by zero")
  } else {
    result := num1 / num2
    fmt.Println("Result: ", result)
  }
}

func main() {

  division(4, 2)
  division(8, 0)
  division(2, 8)

}

输出

Result:  2
RECOVER Cannot divide a number by zero
Result:  0

在上面的示例中,我们创建了一个 handlePanic() 函数来从 panic 状态中恢复。

func handlePanic() {

  // detect if panic occurs or not
  a := recover()

  if a != nil {
    fmt.Println("RECOVER", a)
  }
}

在这里,我们使用 a := recover() 来检测程序中发生的任何 panic,并将 panic 消息赋给 a

在我们的示例中,发生了 panic,因此 a 中会有值。因此,**if 语句** 被执行,它会打印 panic 消息。

division() 函数中,我们调用 handlePanic() 函数。

defer handlePanic()

这里,注意两点

  • **我们在 panic 发生之前调用了 handlePanic()。** 这是因为如果遇到 panic,程序将被终止,而我们希望在终止之前执行 handlePanic()
  • **我们使用 defer 来调用 handlePanic()。** 这是因为我们只希望在 panic 发生后处理它,所以我们推迟了它的执行。
你觉得这篇文章有帮助吗?

我们的高级学习平台,凭借十多年的经验和数千条反馈创建。

以前所未有的方式学习和提高您的编程技能。

试用 Programiz PRO
  • 交互式课程
  • 证书
  • AI 帮助
  • 2000+ 挑战