zoukankan      html  css  js  c++  java
  • go基础第四篇:error、panic、recover

    error

    error是go自带的一个接口,只有一个Error()方法,没有入参,有一个string类型的出参。

    go自带了很多实现了error接口的struct,如errorString、TimeoutError、DNSError等。

    errorString只有一个string型的属性,我们可以通过errors包的New(text string)函数获取指向errorString实例的指针。示例如下:

    func Check(i int) (int, error) {
        if i < 0 {
            return -1, errors.New("negative")
        } else {
            return 1, nil
        }
    }
    
    func main() {
        i, err := Check(-1)
        if err != nil {
            fmt.Println("something wrong")
        } else {
            fmt.Println("going on,i=", i)
        }
    }

    error实例能否用==比较?

    github.com/pkg/errors是一个比较好用的error相关的包。

    panic

    panic是个函数,有一个空接口类型的入参(可传任意类型,如字符串、error等等),无出参,作用类似于java中的throw new RuntimeException(msg),panic之后的代码不执行,程序会非零退出。

    func main() {
        fmt.Println(1)
        panic("something wrong")
        fmt.Println(2)
    }

    只会打印1,不会打印2,main函数非零退出。

    recover

    recover也是个函数,没有入参,出参是个空接口类型,具体返回什么类型取决于使用的场景:

    如果recover()在defer后面的函数中调用,则如果goroutine panic了,则recover()函数返回panic函数的入参,同时panic会被压制住,程序不会非零退出了,否则返回nil。如果不是在defer后面的函数中调用,则返回nil,且不会压制panic。

    recover()函数不包装进一个函数中调用,而是直接在defer后面调用的话,没有任何效果。

    recover()函数作用有点像java中的catch,因为它在一些情况下可以压制panic。但不是完全一样。因为recover()函数在类似finally块中执行才有意义,而catch没有在finally块中。

    示例如下:

    func MayPanic(i int) int {
        if i == 0 {
            panic("不能为0")
        } else if i < 0 {
            panic(errors.New("不能小于0"))
        }
        return 1
    }
    
    func main() {
        defer func() {
            if r := recover(); r != nil {
                fmt.Println(r)
                fmt.Println(reflect.TypeOf(r))
            }
        }()
        //i := MayPanic(0)
        i := MayPanic(-1)
        fmt.Println(i)
    }

    上例中,recover()在defer后面的函数中调用,且协程执行panic(errors.New("不能小于0"))而panic了,所以recover()函数返回error。main函数不会非零退出。

    func main() {
        func() {
            if r := recover(); r == nil {
                fmt.Println(r)
                fmt.Println(reflect.TypeOf(r))
            }
        }()
        i := MayPanic(1)
        fmt.Println(i)
    }

    上例中,recover()函数虽然在defer后面的函数中调用,但是协程没有panic,所以recover()函数返回nil。

    func MayPanic(i int) int {
        if i == 0 {
            panic("不能为0")
        } else if i < 0 {
            panic(errors.New("不能小于0"))
        }
        return 1
    }
    
    func main() {
        func() {
            if r := recover(); r == nil {
                fmt.Println(r)
                fmt.Println(reflect.TypeOf(r))
            }
        }()
        i := MayPanic(-1)
        fmt.Println(i)
    }

    上例中,recover()不是在defer后面的函数中调用的,所以返回值是nil。

  • 相关阅读:
    得到相对Plugin的路径
    GEF常见问题4:非矩形图元
    在Eclipse的About对话框上添加自己的图标
    用GMF生成简化的数据库设计器
    全超实用的Javascript类库和jQuery插件大全之一:图片,地图和图形
    #敏捷个人# 第二批敏捷个人推广者实践团报名
    2012年最新的12款超棒jQuery插件
    《敏捷个人》周刊 第14期 (可下载)
    时间管理:敏捷个人时中法卡片
    #敏捷个人# 实践团报名
  • 原文地址:https://www.cnblogs.com/koushr/p/13371290.html
Copyright © 2011-2022 走看看