20年第35周:go defer,panic,recover,异常处理

go中可以抛出一个panic的异常,然后在defer中通过recover捕获这个异常,然后正常处理。

一、go的defer

1.1 go defer 介绍

defer后边会接一个函数,但该函数不会立刻被执行,而是等到包含它的程序返回时(包含它的函数执行了return语句、运行到函数结尾自动返回、对应的goroutine panic)defer函数才会被执行。通常用于资源释放、打印日志、异常捕获等

1.2 多个go defer 的执行顺序

go的defer函数,调用顺序类似于,越后面的defer函数越先被执行(后进先出)

func main() {
    defer fmt.Printf("我")
    defer fmt.Printf("是")
    defer fmt.Printf("三")
    defer fmt.Printf("火")
}

输出结果:

火三是我

1.3 go defer 最佳实践

推荐


import (
    "fmt"
    "io"
    "os"
)

func main() {
    // 打开文件
    // fp, err := os.Open("./test.txt")  // 只读方式打开
    fp, err := os.OpenFile("./test.txt", os.O_CREATE|os.O_APPEND, 6) // 读写方式打开
    if err!=nil {
        // 错误处理
    }
    defer fp.Close()  //如果成功打开了文件,就关闭文件,释放资源。

    doSomething(A) // 做了A事情

    doSomething(B) // 做了B事情

    doSomething(C) // 做了C事情

    
    
    return 
}

不推荐


import (
    "fmt"
    "io"
    "os"
)

func main() {
    // 打开文件
    // fp, err := os.Open("./test.txt")  // 只读方式打开
    fp, err := os.OpenFile("./test.txt", os.O_CREATE|os.O_APPEND, 6) // 读写方式打开
    if err!=nil {
        // 错误处理
    }
    doSomething(A) // 做了A事情

    doSomething(B) // 做了B事情

    doSomething(C) // 做了C事情

    defer fp.Close()  //关闭文件,释放资源。这里写着写着可能就忘了关了。
    
    return 
}

二、go panic

2.1 go panic 介绍

1、内建函数
2、假如函数F中书写了panic语句,会终止其后要执行的代码,在panic所在函数F内如果存在要执行的defer函数列表,按照defer的逆序执行
3、返回函数F的调用者G,在G中,调用函数F语句之后的代码不会执行,假如函数G中存在要执行的defer函数列表,按照defer的逆序执行,这里的defer 有点类似 try-catch-finally 中的 finally
4、直到goroutine整个退出,并报告错误

三、go recover

3.1 go recover 介绍

1、内建函数
2、用来控制一个goroutine的panicking行为,捕获panic,从而影响应用的行为
3、一般的调用建议
a). 在defer函数中,通过recever来终止一个gojroutine的panicking过程,从而恢复正常代码的执行
b). 可以获取通过panic传递的error

3.2 go panic recover 最佳实践

不推荐

// 使用error的写法
func first() error {return nil}
func second() error {return nil}
func third() error {return nil}
func fourth() error {return nil}
func fifth() error {return nil}

func Do() error {
    var err error
    // 套娃
    if err = first(); err == nil {
        if err = second(); err == nil {
            if err = third(); err == nil {
                if err = fourth(); err == nil {
                    if err = fifth(); err == nil {
                        return nil
                    }
                }
            }
        }
    }
    return err
}

推荐

// panic 写法
func Do2() (err error) {
    defer func(){
        if r:= recover() ; r!= nil{
            err = fmt.Errorf("Error: %+v", r)
        }
    }()
    first2()
    second2()
    third2()
    fourth2()
    fifth2()
    return
}

你可能感兴趣的:(20年第35周:go defer,panic,recover,异常处理)