Golang的异常处理实战篇

          Golang的异常处理实战篇

                             作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

 

 

  Go语言的异常捕获要比Python中简单的多,它没有Python中那么多复杂的异常类型及继承体系。接下来我们来一起体验一下Golang的异常处理。

 

 

一.代码运行时出错应该怎样处理呢?

1>.算数除零异常案例

package main

import (
    "fmt"
)

func main() {
    //定义除数
    a := 20

    //定义被除数
    b := 0

    //除数不能为0,编译时并不会报错,但是在代码运行时会报错哟~
    c := a / b

    //由于上面的代码执行报错啦,该行代码不会被执行
    fmt.Printf(" %d ➗ %d = %d\n", a, b, c)
}

2>.数组索引越界异常案例

package main

import (
    "fmt"
)

func myArr(index int) {

    //定义数组
    var arr [10]int

    //数组这里赋值时可能会存在一个风险,即索引越界异常
    arr[index] = 123

    fmt.Println(arr)
}

func main() {
    myArr(12)
}

 

二.Go语言中自定义异常接口

1>.使用errors自定义异常消息(并不会使得程序崩溃)

package main

import (
    "errors"
    "fmt"
)

func div(x int, y int) (res int, err error) {

    if y == 0 {
        /*
            Go语言引入了一个关于错误处理的标准模式,即error接口,该接口需要导入"errors"包:
                errors接口适合返回可控的错误,即我们知道在某个代码块中可能会出现的异常。
        */
        err = errors.New("div函数除零异常...")
        return
    }
    res = x / y
    return
}

func main() {
    a := 10
    b := 0

    /*
        res:
            用来接收运算结果
        err:
            用来接收错误消息
        nil:
            表示空,"if err != nil"表示变量err接收的错误消息是否为空。
    */
    res, err := div(a, b)
    if err != nil {
        fmt.Println(err)
        //log.Fatal(err) //我们也可以使用log包来帮助咱们输出错误,它会在错误消息签名自动加上日期时间
    } else {
        fmt.Println(res)
    }

    fmt.Println("代码执行完毕")
}

2>.使用panic自定义异常消息(程序会崩溃)

package main

import (
    "fmt"
)

func myArr2(index int) {

    //定义数组
    var arr [10]int

    if index >= 10 {
        /*
            panic函数与errors接口不同:
                (1)使用panic时无需导入包;
                (2)若出现异常,使用panic封装异常消息时,会直接导致程序运行结束,换句话说,error是一般性错误,而panic函数返回的是让程序崩溃的错误

            温馨提示:
                一般而言,当panic异常发生时,程序会中断运行。随后,程序崩溃并输出日志消息。日志信息包括panic value和函数调用的堆栈跟踪信息
                当然,如果直接调用内置的panic函数也会引发panic异常,panic函数接收任何值作为参数。
        */
        panic("请注意,index > 10,出现了索引越界异常...(index的取值范围0~9)")
    }

    //上面使用了panic接口封装了异常处理错误,因此如果代码到这一行说明没有索引越界异常
    arr[index] = 123
    fmt.Println(arr)
}

func main() {

    myArr2(12)

    fmt.Println("代码执行完毕")
}

 

三.使用recover进行异常捕获

1>.defer延迟调用

package main

import (
    "fmt"
)

func main() {

    /*
        defer语句被用于预定对一个函数的调用。可以把这类被defer语句调用的函数称为函数。

        defer的应用场景:
            (1)释放占用的资源;
            (2)捕获异常处理
            (3)输出日志

        温馨提示:
            如果一个函数中有多个defer语句,它们会以LIFO(后进先出)的顺序执行。

        先不要运行代码,你先猜猜下面的代码的执行顺序。
    */
    defer fmt.Println("\thttps://www.cnblogs.com/yinzhengjie/")

    fmt.Println("我的名字叫尹正杰,英文名叫'Jason Yin'.爱好开源技术.")

    defer fmt.Println("\thttps://www.cnblogs.com/yinzhengjie2020")

    fmt.Println("我的博客是:")
}

2>.defer结合recover进行错误拦截

package main

import "fmt"

func test3(index int) {
    /*
        错误拦截要在产生错误前设置,因此建议大家把错误拦截的函数放在函数内部的首行定义。
    */
    defer func() {
        /*
            运行时panic异常一旦被引发就会导致程序崩溃
            Go语言提供了专用于"拦截"运行时panic的内建函数"recover"。
            它可以使当前的程序从运行时panic的状态中恢复并重新获得流程控制权,欢聚话说,通过recover进行不可控的错误拦截,重新获取程序的控制权
        */
        err := recover()
        if err != nil {
            fmt.Println(err)
        }
    }()

    /*
        定义容量为10的数组
    */
    var arr [10]int

    if index >= 10 {
        panic("请注意,index > 10,出现了索引越界异常...(index的取值范围0~9)")
    }

    arr[index] = 123

    fmt.Println(arr)
}

func main() {
    test3(5)
    test3(12)
    fmt.Println("代码执行完毕")
}

 3>.面试题(请根据下面代码手写出输出结果)

package main

import (
    "fmt"
)

func f1() (int, error) {
    defer fmt.Println(1)
    defer fmt.Println(2)
    fmt.Println(3)
    return fmt.Println(4)
}

func f2() (int, error) {
    defer fmt.Println(5)
    defer fmt.Println(6)
    fmt.Println(7)
    f1()

    defer func() (int, error) {
        defer fmt.Println(8)
        fmt.Println(9)
        return fmt.Println(10)
    }()

    return fmt.Println(11)
}

func main() {
    f2()
}

 

posted @ 2020-02-18 06:57  JasonYin2020  阅读(1318)  评论(0编辑  收藏  举报