Go语言学习日记【三十二】golang代码错误处理【error,defer,recover】

前言:

        代码异常处理是学习任何编程语言都需要考虑的一个重要话题。比如C++,python都引入exception的概念和try_catch  try_except的引入。golang自然也有自己独特的异常处理方式。漂亮的异常处理方式也是golang语言最大的亮点之一,下面重点解析一下golang错误处理方式。

一、error接口

       Go语言引入了一个关于错误处理的标准模式,即 error 接口,该接口的定义如下:

type error interface {
    Error() string
}

         在golang代码中,对于大多数函数,如果要返回错误,大致上都可以定义为如下模式

func myFunc(param string)(str string, err error) {
    // ...
}

         将 error 作为多种返回值中的最后一个,但这并非是强制要求

         调用时的代码建议按如下方式处理错误情况        

_, err := myTest("test")
if err != nil {
    // 错误处理
} else {
    // ......
}

        同时,在代码中,我们可以自定义error类型,举例如下

type DefineError struct {
    Define string
    Err error
}

// 定义Error函数
func (d *DefineError) Error() string {
    return d.Define + d.Err.Error()
}

       这样,当函数调用失败返回 err 时,将该 err 包装到一个 DefineError 对象中返回

func Stat() (err error) {
    err = myFunc()
    if err != nil {
        return nil, &DefineError{"define", err}
    }
    // ......
}

二、defer

        在函数编写过程中,有时引入异常会导致代码异常退出,但是,之前打开的诸如文件句柄这些操作如果不关闭,会导致程序在运行过程中出现问题。而在golang语言中,通过defer关键字轻轻松松的解决了这个问题。

        代码示例:

package main

import "fmt"

func main()  {
    defer fmt.Println("main defer:1")
    defer fmt.Println("main defer:2")
    fmt.Println("main --:1")
    panic("--- error ---")
    fmt.Println("main --:2")
    defer fmt.Println("main defer:5")
    defer fmt.Println("main defer:6")
}


/*
main --:1
main defer:2
main defer:1
panic: --- error ---

goroutine 1 [running]:
main.main()
*/

        通过代码测试可以看出,当程序出现异常时,程序异常部分下面的代码将不再执行,而异常上面部分的defer代码,将在异常抛出后逆序执行。因此,当我们把要执行的句柄操作通过defer放在函数起始位置,无论程序执行是否异常,句柄关闭操作都能在程序里安全执行。

三、panic与recover

        panic:在函数中如果书写并触发了panic语句,会终止其后要执行的代码。在panic所在函数内如果存在要执行的defer函数列表,则按照defer书写顺序的逆序执行,同时,如果该函数被其他函数调用,则调用函数在调用代码后面的代码都不会执行,如果存在defer语句,一样逆序执行。在代码最后,则抛出panic异常。代码示例:

package main

import "fmt"

func main()  {
    defer fmt.Println("main defer:1")
    defer fmt.Println("main defer:2")
    fmt.Println("main --:1")
    myTest()
    fmt.Println("main --:2")
    defer fmt.Println("main defer:5")
    defer fmt.Println("main defer:6")
}

func myTest() {
    defer fmt.Println("myTest defer:1")
    defer fmt.Println("myTest defer:2")
    fmt.Println("myTest --:1")
    panic("manaual error")
    defer fmt.Println("myTest defer:4")
    defer fmt.Println("myTest defer:5")
}

/*
main --:1
myTest --:1
myTest defer:2
myTest defer:1
main defer:2
main defer:1
panic: manaual error

goroutine 1 [running]:
main.myTest()
	D:/code/go/go/01-错误演示.go:19 +0x165
main.main()
	D:/code/go/go/01-错误演示.go:9 +0x173

Process finished with exit code 2
*/

      recover:

  1. recover的作用是捕获panic,从而恢复正常代码执行;
  2. recover必须配合defer使用;
  3. recover没有传入参数,但是有返回值,返回值就是panic传递的值

     代码示例:

package main

import "fmt"

func main()  {
    defer fmt.Println("main defer:1")
    defer fmt.Println("main defer:2")
    fmt.Println("main --:3")
    myTest()
    fmt.Println("main --:4")
    defer fmt.Println("main defer:5")
    defer fmt.Println("main defer:6")
}

func myTest() {
    defer fmt.Println("---------------")
    defer func() {
        if msg := recover(); msg != nil {
            fmt.Println("panic信息:", msg, "---recover恢复---")
        }
    }()
    defer fmt.Println("myTest defer:1")
    defer fmt.Println("myTest defer:2")
    fmt.Println("myTest --:1")
    panic("manaual error")
    defer fmt.Println("myTest defer:4")
    defer fmt.Println("myTest defer:5")
}

/*
Process finished with exit code 0

*/

  • 16
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 16
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值