golang的异常处理

作者: CodingCode | 来源:发表于2018-05-25 15:23 被阅读45次

    go语言是不支持异常的,go语言的设计者认为异常会被不成熟的程序员滥用,导致异常的处理过去复杂;go语言取消异常的一个替代办法是使用多返回值。

    func foo(param1, param2, ...) (retval1, retval2, ...)
    

    通常的函数实现里面,会使用一个error对象来表示是否成功,这其实类似于是否有异常发生

    if val, err := foo(...); err != nil {
        // exception occured
    }
    // normal call flow
    

    其实我个人觉得,像java语言的异常设计的已经比较合理了,完全可以保留使用,而不是丢弃;当然C++的异常是不完美的,是应该被禁用,因为C++的异常设计有本身的缺陷,主要是C++为了兼容C而导致的兼容性问题,历史包袱啊。

    go语言的异常
    go语言还是保留了一个异常处理的入口,那就是panic/recover/defer

    作用如下

    • panic负责产生一个异常
    • defer里面t通过recover来捕获异常

    panic是一个内置函数,原型定义如下:

    func panic(v interface{})
    

    recover也是一个内置函数,原型定义如下:

    func recover() interface{}
    

    panic的参数是一个interface类型,recover的返回值也是一个interface类型;其实panic()的参数正好就是recover()函数的返回值,就是这么传递过去的。

    举例子来说:

    package main
    
    import (
        "fmt"
        "reflect"
    )
    func foo() {
        defer func() {
            if e := recover(); e != nil {
                fmt.Printf("recover type =[%v]\n\tvalue=[%v]\n", reflect.TypeOf(e), reflect.ValueOf(e))
            }
        }()
        panic(12)
    }
    func main() {
        foo()
    }
    

    运行结果:

    recover type =[int]
            value=[12]
    

    例子2:

    package main
    
    import (
        "fmt"
        "reflect"
    )
    
    func foo() {
        defer func() {
            if e := recover(); e != nil {
                fmt.Printf("recover type =[%v]\n\tvalue=[%v]\n", reflect.TypeOf(e), reflect.ValueOf(e))
            }
        }()
        panic(fmt.Errorf("meet an error"))
    }
    
    func main() {
        foo()
    }
    

    运行结果:

    recover type =[*errors.errorString]
            value=[meet an error]
    

    例子3:
    这是一个异常链,也就是在一个function里面panic了,然后在上层caller里面捕获这个异常:

    package main
    
    import (
        "fmt"
        "reflect"
    )
    
    func foo() {
        panic("error in foo")
    }
    
    func main() {
        defer func() {
            if e := recover(); e != nil {
                fmt.Printf("recover type =[%v]\n\tvalue=[%v]\n", reflect.TypeOf(e), reflect.ValueOf(e))
            }
        }()
    
        foo()
    }
    

    运行

    recover type =[string]
            value=[error in foo]
    

    我们看到异常发生在foo()函数里面,但是捕获这个异常的是在main()函数里面。

    相关文章

      网友评论

      本文标题:golang的异常处理

      本文链接:https://www.haomeiwen.com/subject/yvxujftx.html