zoukankan      html  css  js  c++  java
  • GoLang之错误处理

    错误处理

     

    error

    Go语言引入了一个错误处理的标准模式,即error接口,该接口定义如下:

    type error interface {
        Error() string
    }

    对于大多数函数,如果要返回错误,可以将error作为多返回值的最后一个:

    func foo(param int)(ret int, err error)
    {
      ...  
    }

    调用时的代码:

    n, err := foo(0)
    if err != nil {
        //  错误处理
    } else {
        // 使用返回值n
    }

    我们还可以自定义错误类型,一个例子:

    package main
     
    import "fmt"
    import "errors"
     
    //自定义的出错结构
    type myError struct {
        arg  int
        errMsg string
    }
    //实现Error接口
    func (e *myError) Error() string {
        return fmt.Sprintf("%d - %s", e.arg, e.errMsg)
    }
     
    //两种出错
    func error_test(arg int) (int, error) {
        if arg < 0  {
             return -1, errors.New("Bad Arguments - negtive!")
         }else if arg >256 {
            return -1, &myError{arg, "Bad Arguments - too large!"}
        }
        return arg*arg, nil
    }
     
    //相关的测试
    func main() {
        for _, i := range []int{-1, 4, 1000} {
            if r, e := error_test(i); e != nil {
                fmt.Println("failed:", e)
            } else {
                fmt.Println("success:", r)
            }
        }
    }

    defer 

    你可以在Go函数中添加多个defer语句,当函数执行到最后时,这些defer语句会按照逆序执行(即最后一个defer语句将最先执行),最后该函数返回。

    特别是当你在进行一些打开资源的操作时,遇到错误需要提前返回,在返回前你需要关闭相应的资源,不然很容易造成资源泄露等问题。如下代码所示,我们一般写打开一个资源是这样操作的:

    func CopyFile(dst, src string) (w int64, err error) {
        srcFile, err := os.Open(src)
        if err != nil {
            return 
        }
    
        defer srcFile.Close()
    
        dstFile, err := os.Create(dst)
        if err != nil {
            return 
        }
    
        defer dstFile.Close()
    
        return io.Copy(dstFile, srcFile)
    }

    如果defer后面一条语句干不完清理工作,也可以使用一个匿名函数:

    defer func(){
        ...
    }()


    注意,defer语句是在return之后执行的,例如:

    func test() (result int) {
        defer func() {
            result = 12
        }()
        return 10
    }
    
    func main() {
        fmt.Println(test())     // 12
    }

    panic() recover()

    panic()函数用于抛出异常,recover()函数用于捕获异常,这两个函数的原型如下:

    func panic(interface{})
    func recover() interface{}

    当在一个函数中调用panic()时,正常的函数执行流程将立即终止,但函数中之前使用defer关键字延迟执行的语句将正常展开执行,之后该函数将返回到调用函数,并导致逐层向上执行panic()流程,直至所属的goroutine中所有正在执行的函数被终止。错误信息将被报告,包括在调用panic()函数时传入的参数,这个过程称为错误流程处理。

    panic()接受一个interface{}参数,可支持任意类型,例如:

    panic(404)
    panic("network broken")
    panic(Error("file not exists"))

    在defer语句中,可以使用recover()终止错误处理流程,这样可以避免异常向上传递,但要注意recover()之后,程序不会再回到panic()那里,函数仍在defer之后返回。


    func foo() { panic(errors.New("i'm a bug")) return } func test() (result int) { defer func() { if r := recover(); r != nil { err := r.(error) fmt.Println("Cache Exception:", err) } }() foo() return 10 } func main() { fmt.Println(test()) // 0 }

    注意,在一个函数中panic被调用后,其defer语句仍会执行,

    func foo()(n int) {
        defer func() {
            if r := recover(); r != nil {
                n++    // take effective
            }
        }()
        n++             // take effective
        panic(errors.New("i'm a bug"))
        n++             // take no effective
        return n
    }
  • 相关阅读:
    python:时间格式转化
    python:将时间戳格式化为yyyyMMdd hh:mm:ss
    Oracle 实现表中id字段自增长
    django:将query-set类型转为json类型
    mysql:获取某个表的所有字段
    Navicat连接Mysql8.0.11出现1251错误
    Java垃圾回收(GC)机制详解
    Mybatis学习总结(九)——查询缓存
    Mybatis学习总结(八)——延迟加载
    Mybatis学习总结(七)——调用存储过程
  • 原文地址:https://www.cnblogs.com/chenny7/p/7885674.html
Copyright © 2011-2022 走看看