go语言defer,panic,recover 与错误处理

三个关键字

defer:在函数中,经常要打开资源(如:文件打开,数据库连接等),为了在函数执行后,及时释放资源,go的设计者提供defer(延时机制)

panic:内置函数,接收一个interface{}类型的值(也就是任何值)作为参数,可接收error类型的变量,输出错误信息,并退出程序。

errors.New("错误说明"):返回一个error类型的值,表示一个错误

recover:内置函数,可以捕获到go中的异常

defer的单独使用

package main

import (
    "fmt"
)

func deferTest() int{
    defer fmt.Println("aaaaaaaaaaaaaaaaa")  // 先不执行,知道函数执行完成后执行该语句;如果前面有一语句为打开数据库,那么我们可以立刻在该语句后使用defer修饰关闭数据库代码,而不影响函数中间的代码执行,避免后续忘记关闭数据库
    fmt.Println("bbbbbbbbbbbbbbbbb")
    return 2
}

func main(){
    fmt.Println("deferTest:",deferTest())
}

defer 关键字修饰的语句会被压入一个栈,且不会执行该语句;当函数执行完成后,按照先进后出的方式,执行defer压入栈中的语句。

因此执行结果如下:

bbbbbbbbbbbbbbbbb
aaaaaaaaaaaaaaaaa
deferTest: 2

 defer、panic、recover组成的错误处理

go语言不支持 try...catch...finally,取而代之的是 defer、panic、revocer组合

例子一

看以下代码:

package main
import (
    "fmt"
)
func deferTest2(){
    var num1 int8 = 10
    var num2 int8 = 0
    fmt.Println("函数内部代码")
    fmt.Println(num1 / num2)   // 在这里程序 panic了,因此在该位置退出,且程序不会执行后面的代码
}
func main(){
    deferTest2()
    fmt.Println("后面的代码...")
}

运行结果如下:

 使用 defer ,revocer 进行错误处理后,任然可以执行后面的代码,因此修改代码如下:

package main
import (
    "fmt"
)
func deferTest2(){
    defer func(){   // 函数发生异常后会执行 defer里的代码,并且不会退出程序
        err := recover()
        if err != nil {
            fmt.Println("发生异常:",err)
        }
    }()
    var num1 int8 = 10
    var num2 int8 = 0
    fmt.Println("函数内部代码")
    fmt.Println(num1 / num2)   
}
func main(){
    deferTest2()
    fmt.Println("后面的代码...")
}

执行结果如下:

 例子二,自定义错误,使用panic 输出错误程序后,退出程序

package main

import (
    "fmt"
    "errors"
)
func myError(a string) (err error){
    if a == "a" {
        return nil
    }
    return errors.New("这是一个自定义错误")
}
func doMyError(){
    err := myError("b")
    if err != nil {   // 如果有错误,则打印错误,并退出程序
        panic(err)    
    }
    fmt.Println("继续向后执行...")
}
func main(){
    doMyError()
    fmt.Println("后面的代码...")
}

执行结果为:

 当 myError 传 a的时候,执行结果如下:

 我们再上面代码加入defer语句处理错误后:

import (
    "fmt"
    "errors"
)
func myError(a string) (err error){
    if a == "a" {
        return nil
    }
    return errors.New("这是一个自定义错误")
}
func doMyError(){
    defer func(){
        err := recover()
        if err != nil {
            fmt.Println("出现的error为:",err)
        }
    }()
    err := myError("b")
    if err != nil {
        panic(err)   // 发生panic 后,执行压入栈的defer语句,且程序不会终止
    }
    fmt.Println("继续向后执行...")  // 发生panic 后不会执行该语句
}
func main(){
    doMyError()
    fmt.Println("后面的代码...")
}

执行结果为:

 

posted @ 2024-01-04 22:10  远洪  阅读(255)  评论(0编辑  收藏  举报