• 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。

  • 相关阅读:
    windows下安装nginx
    java 32位MD5加密的大写字符串
    eclipse运行maven的jetty插件内存溢出
    Phpstorm Alt+Enter 自动导入类
    CSS 再学习,文本处理
    1406 data too long for column 'content' at row 1
    tp5.1报错 页面错误!请稍后再试
    lnmp升级php
    Tp5,Service使用
    CSS再学习 之背景色 背景图片
  • 原文地址:https://www.cnblogs.com/koushr/p/13371290.html
Copyright © 2020-2023  润新知