zoukankan      html  css  js  c++  java
  • GO语言Error处理

    Go语言没有提供像Java、C#、Python语言中的try...catch异常处理方式,而是通过函数返回值逐层往上抛。好处就是避免漏掉本应处理的错误。坏处是代码啰嗦。

    错误与异常区别

    错误指的是可能出现问题的地方出了问题,比如打开文件失败。
    异常是不应该出现问题的地方出了问题,比如空指针。
    Go中的错误是一种类型,错误用内置的error类型(接口)来表示。错误可以存储在变量中,从函数中返回。

    type error interface {
        Error() string
    }
    

    创建自定义错误

    创建自定义错误可用errors包下的New()函数以及fmt包下的Errorf()函数。

    //创建一个error的数据
        err1 := errors.New("自己创建...")
        fmt.Println(err1)
        fmt.Printf("%T
    ", err1) //*errors.fundamental
        //创建一个error方法
        err2 := fmt.Errorf("错误码:%d", 10000)
        fmt.Println(err2)   //错误码:10000
        fmt.Printf("%T
    ", err2)    //*errors.errorString
    

    自定义错误示例

    //求矩形面积
    type areaError struct {
        msg    string  //错误描述
        length float64 //矩形长度
        wigth  float64 //矩形宽度
    }
    
    func (e *areaError) Error() string {
        return e.msg
    }
    func (e *areaError) lengthNegative() bool {
        return e.length < 0 //如果比0小,返回false
    }
    func (e *areaError) wigthNegative() bool {
        return e.wigth < 0 //如果比0小,返回false
    }
    func revArea(length, wigth float64) (float64, error) {
        msg := ""
        if length < 0 {
            msg = "长度小于0"
        }
        if wigth < 0 {
            if msg == "" {
                msg = "宽度小于0"
            } else {
                msg += ",宽度小于0"
            }
        }
        if msg != "" {
            return 0, &areaError{msg, length, wigth}
        }
        return length * wigth, nil
    }
    func main() {
        length, wigth := -4.3, -6.7
        area, err := revArea(length, wigth)
        if err != nil {
            fmt.Println(err)
            //断言判断具体error
            if err, ok := err.(*areaError); ok {
                if err.lengthNegative() {
                    fmt.Printf("error:长度,%.2f小于0
    ", err.length)
                }
                if err.wigthNegative() {
                    fmt.Printf("error:宽度,%.2f小于0
    ", err.wigth)
                }
            }
            return
        }
        fmt.Println("矩形面积是:", area)
    }
    输入:
    长度小于0,宽度小于0
    error:长度,-4.30小于0
    error:宽度,-6.70小于0
    

    panic/recover

    GO可以使用panic/recover模式来处理错误。 panic可以在任何地方引发,但recover只有在defer调用的函数中有效。
    等到包含defer语句的函数执行完毕时,延迟函数(defer后的函数)才会被执行,而不管包含defer语句的函数是通过return的正常结束,还是由于panic导致的异常结束,你可以在一个函数中执行多条 defer语句,它们的执 行顺序与声明顺序相反。

    panic:

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

    recover

    1. 内建函数
    2. 用来控制一个goroutine的panicking行为,捕获panic,从而影响应用的行为
    3. 一般的调用建议:在defer函数中,通过recever来终止一个goroutine的 panicking过程,从而恢复正常代码的执行;可以获取通过panic传递的 error
      简单来讲go中可以抛出一个panic的异常,然后在defer中通过recover捕获这个异常,然后正常处理.

    实例

    func a()  {
        fmt.Println("func a")
    }
    func b()  {
        panic("func b")
    }
    func c()  {
        fmt.Println("func c")
    }
    func main()  {
        a()
        b()
        c()
    }
    

    执行到func b的时候会抛出异常,程序崩溃,可以使用recover将程序恢复

    func a()  {
        fmt.Println("func a")
    }
    func b()  {
        defer func() {//捕获panic抛出的异常
            err := recover()
            if err != nil{
                fmt.Println("recover fun b")
            }
        }()
        panic("func b")
    }
    func c()  {
        fmt.Println("func c")
    }
    func main()  {
        a() //func a
        b() //recover fun b
        c() //func c
    }
    
    • recover()必须搭配defer使用。
    • defer一定要在可能引发panic的语句之前定义。
  • 相关阅读:
    SQL Server查询死锁并KILL
    android之Widget01
    android之RatingBar控件用法
    android之SeekBar控件用法
    android之ExpandableListActivity
    【原创】开源.NET排列组合组件KwCombinatorics使用(一)—组合生成
    【吐槽】博客园新的原创文章在搜索引擎的排名不及转载的站点
    【资源】108个大数据文档PDF开放下载-整理后打包下载
    【原创】.NET平台机器学习组件-Infer.NET连载(二)贝叶斯分类器
    【原创】.NET平台机器学习组件-Infer.NET连载(一)介绍
  • 原文地址:https://www.cnblogs.com/show58/p/12622100.html
Copyright © 2011-2022 走看看