0
点赞
收藏
分享

微信扫一扫

使用 Panic、Defer 和 Recover 处理 Go 错误



via:
​​​https://medium.com/technofunnel/error-handling-in-golang-with-panic-defer-and-recover-d77db7ae3875​​作者:Mayank Gupta

四哥水平有限,如有翻译或理解错误,烦请帮忙指出,感谢!

文章源自 Medium,点赞超过 700+。

原文如下:

这篇文章主要会与大家介绍 Go 语言的错误处理。

我们将会讨论关于 Go 语言创建和捕获自定义、运行时错误的一些简单方法。Go 提供了简单方法实现。

Go 提供了简单的错误接口,每个返回错误都必须实现这个接口。

type error interface {
Error() string
}

创建用户自定义错误

我们可以使用 Go 语言创建简单的用户自定义错误,就像下面这样:

package main

import (
"errors"
"fmt"
)

func calculateArea(radius int) (int, error) {
if radius < 0 {
return 0, errors.New("Provide Positive Number")
}
return radius * radius, nil
}

上面代码很简单,求一个圆的面积,必须保证 radius 是正数。如果参数是负数,将会返回 0 与 用户自定义错误,该自定义错误使用 errors.New() 生成。该函数返回 error 类型的对象并可携带用户自定义错误信息。我们使用负数调用函数,这样调用时就能返回错误:

package main

import (
"errors"
"fmt"
)

func calculateArea(radius int) (int, error) {
if radius < 0 {
return 0, errors.New("Provide Positive Number")
}
return radius * radius, nil
}

func main() {
areaValue, err := calculateArea(-1)
if err != nil {
fmt.Println("Error Encountered...")
return
}

fmt.Println(areaValue)
}

在 main 函数里,我们使用负数调用函数 calculateArea()。参数是负数,所以会返回 error 对象。函数执行完会返回两个值,第一个是面积,第二个是 error 对象。上面的代码,我们会检查函数返回的 error 对象是否是 nil,如果是,函数将会继续执行;否则,错误返回并打印错误信息。

创建自定义函数时,我们应当保证能返回正常值和错误状态。上面的代码展示了处理错误的场景。函数抛出错误的场景有很多,我们也需要研究如何处理这些错误。让我们一起来深入研究下这些方法。

关键字 Defer、Panic 和 Recover

使用 defer 关键字

  1. defer 函数会在调用它的函数返回之前被立即调用;
  2. 可以放在函数的任何位置;
  3. 可以使用 defer 定义释放资源函数;
  4. defer 函数会被执行即使发生报错;

让我们通过一段小程序理解下:

package main

import "fmt"

func returnMessage() {
fmt.Println("This is Simple Defer Function Execution")
}

func main() {
defer returnMessage()
fmt.Println("This is line One")
fmt.Println("This is line Two")
fmt.Println("This is line Three")
}

上面的代码在 main() 函数里使用 defer 关键字定义 returnMessage() 函数调用。一旦主函数执行,在主函数返回之前就会执行 returnMessage() 调用。输出如下:

使用 Panic、Defer 和 Recover 处理 Go 错误_golang

即使调用 returnMessage() 函数的代码写在主函数的第一行,实际却是在主函数返回之前发生调用。这就是 Go 语言里面 defer 关键字的工作原理。

使用 Panic 关键字

panic 可以用来终止程序并且可以自定义错误信息。当发生 panic 时,会发生如下情况:

  1. 当前执行函数立即终止;
  2. defer 定义的任何函数将会被执行;
  3. 整个程序会终止;

我们来看下关于 panic 的例子:

package main

import "fmt"

func executePanic() {
panic("This is Panic Situation")
fmt.Println("The function executes Completely")
}

func main() {
executePanic()
fmt.Println("Main block is executed completely...")
}

上面的代码,在 executePanic() 函数里调用了 panic 函数,一旦 panic 执行,整个程序终止,所以输出如下:

使用 Panic、Defer 和 Recover 处理 Go 错误_java_02

当 panic 函数被调用时,程序会在第 6 行代码退出。panic 函数是另外一种提示发生错误并终止程序的方式,并且还可以自定义错误信息。

defer 与 panic 一起使用

前面说过,如果程序发生 panic,将会调用所有与当前执行线程相关的 defer 函数。defer 函数可以用来释放资源。defer 函数将会在当前执行函数终止之前调用。

一起来看下例子:

package main

import "fmt"

func recoveryFunction() {
fmt.Println("This is recovery function...")
}

func executePanic() {
defer recoveryFunction()
panic("This is Panic Situation")
fmt.Println("The function executes Completely")
}

func main() {
executePanic()
fmt.Println("Main block is executed completely...")
}

上面的代码,在 executePanic() 函数里定义了 defer 函数和 panic 函数。看下输出:

使用 Panic、Defer 和 Recover 处理 Go 错误_golang_03

上面的代码,当执行到 panic 函数时,会立即调用 defer 函数。从执行情况可以看出,defer 函数在程序终止之前会被调用。一旦发生 panic ,所有 defer 函数都会在程序终止之前被调用。

使用 Recovery

一旦发生 panic,程序将会终止。然而在实际生产环境中,发生错误终止的情况是不允许的。我们需要一种从错误中恢复的机制,通过恢复代码避免程序的意外终止。

无论执行函数是否会不会发生 panic,函数返回时,defer 函数总是会被执行。我们可以在 defer 函数中编写恢复代码。

检测 panic 情况

在 defer 定义的函数中,我们需要检测程序执行时是否发生过 panic 的情况。为了能够检测出,我们需要执行 recover 函数。一旦我们执行了 recover 函数,就可以接收到 panic 函数传递的错误信息。这些错误信息作为 panic 的返回输出到 recover 函数。我们不允许正在执行的程序发生意外终止,而是要重新获得对程序的控制。程序控制权重新交还给调用函数,这样调用函数便可以接着向下继续执行。一起来看下例子:

package main

import "fmt"

func recoveryFunction() {
if recoveryMessage := recover(); recoveryMessage != nil {
fmt.Println(recoveryMessage)
}
fmt.Println("This is recovery function...")
}

func executePanic() {
defer recoveryFunction()
panic("This is Panic Situation")
fmt.Println("The function executes Completely")
}

func main() {
executePanic()
fmt.Println("Main block is executed completely...")
}

上面的代码,在 defer 函数内部,我们调用了 recover 函数,该函数返回 panic 抛出的错误信息。因为我们使用了 recover 函数,所以程序并不会立即终止。相反,程序的控制权将会返回给主函数并得以继续执行。看下输出:

使用 Panic、Defer 和 Recover 处理 Go 错误_go_04

我们可以看到,程序并未异常终止。调用函数正常执行并返回 main() 函数,主函数继续运行。

如果我的文章对你有所帮助,点赞、转发都是一种支持!

使用 Panic、Defer 和 Recover 处理 Go 错误_java_05

使用 Panic、Defer 和 Recover 处理 Go 错误_编程语言_06



举报

相关推荐

0 条评论