在 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
在上面的示例中,我们创建了一个执行两个数相除的函数:num1
和 num2
。
在函数内部,我们使用了一个 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 发生后处理它,所以我们推迟了它的执行。