• go语言异常处理 error panic recover defer


    error panic defer

    python中可以用 try except来接收处理异常
    go语言没有这些
    go的错误分为两种,一种是人工手动抛出的错误error, 一种是程序执行出错的异常panic

    defer

    func DoDefer(){
        fmt.Println("在defer之前执行")
        defer fmt.Println("第一个defer")
        defer func() {
            fmt.Println("第二个defer")
        }()
        fmt.Println("我在defer中间,我也执行了")
        defer fmt.Println("第三个defer")
        fmt.Println("函数最后的语句执行了")
    }
    
    func main() {
        DoDefer()
    }
    

    执行结果:

    在defer之前执行
    我在defer中间,我也执行了
    函数最后的语句执行了
    第三个defer
    第二个defer
    第一个defer
    

    结论:
    defer执行时间: 函数其他语句执行完之后
    defer执行顺序: 堆栈顺序,从下往上
    所以说函数中除defer语句之外的代码执行完之后,函数执行完毕,函数指令的堆栈触底上弹,此时开始从下往上执行注册的defer
    defer翻译的意思是推迟,可以理解为是一个执行钩子,并且只在函数执行触底后出栈时才会执行(报错,panic也会导致函数提前出栈)

    panic

    panic是严重异常,如果不进行捕获的话,会导致程序退出
    可以通过recover进行捕获,需要配合defer关键字

    func panicErr(info string) {
        panic("Panic Error " + info)
    }
    
    func MustError() {
        defer func() {
            err := recover()
            fmt.Println("Yes, Cover error", err)
        }()
        fmt.Println("异常之前,即将触发异常")
        panicErr("After")
        fmt.Println("异常之后,异常函数内的代码仍然执行了")
    }
    
    func main() {
        MustError()
        fmt.Println("异常发生后,异常函数之外的代码仍然执行了")
    }
    

    执行结果:

    异常之前,即将触发异常
    Yes, Cover error Panic Error After
    异常发生后,异常函数之外的代码仍然执行了
    

    可以看到,在执行出错的函数之前通过defer注册出栈的函数,当注册之后的函数抛出panic后,会进行正常捕获,捕获的函数MustError内,代码执行按照通常异常处理的方式中断,并且出栈,该函数出错语句之后的代码不再执行
    函数的调用者函数依然可以正常执行

    这和try except / try catch不通,try语法处理完try代码块内的代码,不影响函数try外的代码执行
    但是defer recover 不行,只要报错,整个函数立即终止

    再看另个形式:

    func panicErr(info string) {
        panic("Panic Error " + info)
    }
    
    func MustError() {
        panicErr("Before")
        defer func() {
            err := recover()
            fmt.Println("Yes, Cover error", err)
        }()
        fmt.Println("异常之前,即将触发异常")
        panicErr("After")
        fmt.Println("异常之后,异常函数内的代码仍然执行了")
    }
    
    func main() {
        MustError()
        fmt.Println("异常发生后,异常函数之外的代码仍然执行了")
    }
    
    

    和上面不同的是,在defer注册出栈函数之前,先执行了一次抛出错误的函数,结果就是defer语句无效了
    因为代码入栈仍然是从上往下,还没到注册defer,就已经报错了,所以出栈的时候defer的recover还没注册,自然执行不到了

    所以,defer语句,最好在函数最开始就定义!!!

    error

    error在go里面是error接口的实例,不是异常,更像是一个专用于错误信息的类
    函数通过return的方式来抛出异常,不会像panic或者Python Exception 那样不断往上抛出直到被捕获,如果不接收,代码编译会出错,如果不想处理,可以用 _ 来接收,接收后不进行处理也不会出错, 但是可能会造成编程人员对程序运行的期望出现偏差。

    error的抛出:

    func returnErr(returnError bool) (int, error) {
        if returnError {
            return 1 ,errors.New("Some Error")
        }else {
            return 0, nil
        }
    }
    

    error更像是一种报警信息,告诉程序员函数调用出现了意料之外的情况,需要注意,或者做相应处理
    error不像panic那样强制性的必须处理。

  • 相关阅读:
    从温设计模式
    php pdf转图片
    PHP 微服务集群搭建
    死磕nginx系列--nginx 限流配置
    分别
    一生悲哀
    三十男人的思考
    test markdown
    linux 系统内核空间与用户空间通信的实现与分析<转>
    ue4 SNew补遗
  • 原文地址:https://www.cnblogs.com/haiton/p/14964181.html
Copyright © 2020-2023  润新知