zoukankan      html  css  js  c++  java
  • Go异常处理

      一、error接口

        Go 语言通过内置的错误接口提供了非常简单的错误处理机制

        error类型是一个接口,其定义如下:    

    type error interface {
        Error() string
    }

        我们可以在代码中通过实现error接口来生成错误信息。

        任意结构体,只要实现了 Error 方法,就可以认为是 error 错误类型。

        如,errors.New方法返回的就是一个实现了error接口的结构体实例,因为它是error类型:

    func New(text string) error {
        return &errorString{text}
    }
    
    // errorString is a trivial implementation of error.
    type errorString struct {
        s string
    }
    
    func (e *errorString) Error() string {
        return e.s
    }

        Go提供了两种创建error的方法:

          ①:errors.New

          ②:fmt.Errorf

        不过函数通常在最后的返回值中返回错误信息。使用errors.New 可返回一个错误信息:

    import (
        "errors"
        "fmt"
    )
    
    func Hello(name string) (string, error) {
        // If no name was given, return an error with a message.
        if name == "" {
            // return "", fmt.Errorf("empty name")
            return "", errors.New("empty name")
        }
    
        // If a name was received, return a value that embeds the name
        message := fmt.Sprintf("Hi, %v. Welcome!", name)
        return message, nil
    }

          我们会约定最后返回值为 error 类型,一般常见于第二个返回值,这是一个约定俗成的习惯。

        因此在调用返回error的方法的时候要注意判断error是否为nil,如果不为nil,说明异常,要做异常处理:

    import (
        "fmt"
        "log"
    )
    
    func main() {
        message, err := Hello("")
        // If an error was returned, print it to the console and
        // exit the program.
        if err != nil {
            log.Fatal(err)
        }
    
        // If no error was returned, print the returned message
        // to the console.
        fmt.Println(message)
    }

       

      二、panic

        panic是一个Go内置函数,它用来停止当前常规控制流并启动panicking(运行时恐慌)过程。

        panic的触发有两种:

          ①:在运行时遇到错误触发 panic,比如越界访问数组,不相同类型的变量强制类型转换等

          ②:通过显式直接调用 panic 函数触发 panic

            func panic(v interface{}) panic  panic函数接收一个interface{}空接口类型的参数,也就是说,panic函数可以接收一个任意类型的参数。  

    func test() {
        // 显式调用panic
        panic("panic error!")
    }

        怎么处理panic呢?

          异常的使用场景简单描述:Go中可以抛出一个panic的异常,然后在defer中通过recover() 捕获这个异常,将 panic 错误写入日志文件,将程序恢复正常执行

          调用recover() 函数可以捕获panic,即通过recover() 获取panic。

          但是recover() 函数仅在defer函数内部使用。所以想要使用recover捕获panic,我们需要结合defer一起使用。而且,程序在触发panic异常后,不会继续往下执行代码,只能执行defer调用的函数。 

    func a() int{
        i:=0
        return 10/i
    }
    
    func main() {
        // 捕获处理panic
        defer func(){
            if r := recover(); r != nil {
                fmt.Printf("panic recover:%s", r)
            }
        }()
        // 触发panic
        a()
        // 不会再执行
        fmt.Println("123")
    }

          recover()是Go语言一个内置函数,可以重新获取对一个运行时恐慌的 goroutine 的控制。recover 仅在 defer 延迟函数内部使用。在正常执行程序中,调用 recover 函数,将返回 nil。如果当前 goroutine 处于恐慌状态,调用 recover 会捕获提供给 panic 的值并恢复正常执行。

          通常,我们不会去捕获运行时 panic,发生 panic 异常,直接让程序崩溃即可,及时根据 panic 提供的信息,修复异常。但是,一些情况下,我们还是需要捕获 panic,比如在程序发生 panic 异常时,释放资源。比如关闭文件或者释放锁

        

        注意:

          在Go语言中,recover只在defer调用的函数中有效,并且defer要在panic之前先注册,否则不能捕获异常。当panic被捕获到后,被注册的函数将获得程序控制权

        

        Go实现类似 try catch 的异常处理:

    /*
    实现类似try catch处理,后续代码可正常执行
    fun() 可能触发panic的函数
    hander() panic处理函数
    */
    func Try(fun func(), handler func(interface{})) {
        defer func() {
            if err := recover(); err != nil {
                handler(err)
            }
        }()
        fun()
    }
    
    func main() {
        Try(func() {
            panic("test panic")
        }, func(err interface{}) {
            fmt.Println(err)
        })
    
        // 后续代码可继续执行
        fmt.Println("panic handled")
    }

      error和panic区别:

        error一般是程序员可预知的,会进行合适的处理,例如检测输入是否合法等

        而panic是程序员无法预知的异常,例如空指针或数组越界等

      总结:panic 导致的后果非常严重,会导致程序崩溃,所以我们在处理一些不会影响程序正确运行的错误时,尽量使用 error 处理错误

      

      三、throw

        这个错误类型,在用户侧是没法主动调用的,均为 Go 底层自行调用的,像是大家常见的 map 并发读写,就是由此触发

         

    END.

  • 相关阅读:
    U盘量产体验
    syn/ack攻击
    [转]Moment of inertia of a uniform hollow cylinder
    [转]从技术角度分析星际2
    [转]SCI绝不能抄袭别人的工作
    利用代数方法进行相交检测
    【原创】凝思磐石Linux操作系统,X桌面打开方法
    【原创】Oracle数据库逻辑迁移步骤
    【原创】sybase IQ数据库启动参数——START_ASIQ参数列表
    【原创】ORACLE数据库管理方法学习总结
  • 原文地址:https://www.cnblogs.com/yangyongjie/p/15722776.html
Copyright © 2011-2022 走看看