美文网首页
Go语言异常处理机制

Go语言异常处理机制

作者: 超级皮波9 | 来源:发表于2018-09-29 12:49 被阅读0次

    异常处理

    • 概念
      不按我们预期执行的都可以称为异常

    1. 一种是程序发生异常时,将异常信息反馈给使用者

    • 创建异常信息有两种方法
    • 创建方式1
    fmt.Errorf(" 提示的内容 ")
    
    • 创建方式2
    errors.New("提示的内容")
    
    • 案例
    package main
    
    import (
        "errors"
        "fmt"
    )
    func main() {
    
         if res1,err := division(20,5); err==nil{
    
             fmt.Println("res1 = ",res1)   // res1 =  4
    
         }else {
    
             fmt.Println("err = ",err)
    
         }
    
        if res2,err := division(10,0);err==nil {
            
            fmt.Println(res2)
    
        }else {
    
            fmt.Println(err)  //除法运算除数不能为0
    
        }
    
    }
    
    // 除法运算的函数 运算规则: 除数不能为0
    func division(a,b int)(res int,err error){
        if b==0 {
            //创建错误提示给用户
            err = fmt.Errorf("除法运算除数不能为0")
            err = errors.New("除法运算除数不能为0")
        }else{
            res = a/b
        }
        return
    }
    
    • 注意点
      本质上两个方法底层实现原理都是一样
    //package builtin中定义了一个接口
    
    type Error interface {
        Error() string
    }
    
    //package errors 定义了一个结构体
    
    type errorsString struct {
    
        s string
    
    }
    
    // errorsString结构体实现了builtin中的接口
    func (e *errorsString) Error() string{
        return e.s
    }
    
    // 这个函数是errors 包里面的 所以调用的时候是 errors.New()
    func New(text string)Error{
        return &errorsString{text}
    }
    

    2. 一种是程序发生异常时,立刻退出终止程序 继续运行

    • 终止程序分为两种
    1. 系统自动终止程序
    • 案例
    package main
    
    import "fmt"
    
    func main() {
    
        arr :=[4]int{1,3,5,7}
    
        for i:=0;i<10;i++{
            fmt.Println(arr[i])
        }
        /*  系统打印
            1
            3
            5
            7
            panic: runtime error: index out of range
            
            goroutine 1 [running]:
            main.main()
         */
    
    }
    
    1. 手动终止程序(企业开发不常用)
    • 格式
    panic( "提示的内容" )
    
    package main
    
    import "fmt"
    
    func main() {
    
        res := division(10,5)
    
        fmt.Println(res) // res = 2
    
        res2 := division(10,0)
    
        fmt.Println(res2)  
        /**
        panic: 除数不能为零
        
         */
    
    }
    // 定义除法运算的函数
    func division(a,b int)(res int){
        if b==0 {
            // 手动终止
            panic("除数不能为零")
        }else {
            res = a/b
        }
        return
    }
    

    异常恢复

    • 宗旨 程序不要随意被终止,只要不是程序不能运行, 就尽量让程序运行下去

    • 在Go语言中如果出现了panic异常,可以通过 defer和recover 来实现panic异常的捕获,让程序继续运行

    • 格式

    defer func() {
            if err := recover(); err!= nil {
                fmt.Println("recover捕获到",err)
            }
        }()
    
    • 注意点
    1. deferrecover 必须在panic 抛出异常之前定义
    2. defer无论所在函数是正常结束还是异常结束都会被执行
    3. panic异常会随着函数的调用向栈外传递
      例如: A函数调用了B函数,B函数调用了C函数, C函数抛出了异常panic, 那么这个异常会 一层一层传递到B函数和A函数,也就是说在B函数和A函数中也能捕获异常
    package main
    
    import "fmt"
    
    func main() {
    
        division(10,0)   // recover捕获到 除数不能为零
    
    }
    // 定义除法运算的函数
    func division(a,b int)(res int){
        // defer 必须定义在 panic 抛出异常异常之前
        defer func() {
            if err := recover(); err!=nil{
                fmt.Println("recover捕获到",err)  
            }
        }()
    
        if b==0 {
            // 手动终止
            panic("除数不能为零")
        }else {
            res = a/b
        }
        return
    }
    

    异常恢复其他注意点

    1. 同一个函数中如果有多个异常 那么只有第一个异常会被捕获
    • 案例
    package main
    
    import "fmt"
    
    func main() {
    
        defer func() {
            if err := recover(); err!=nil {
                fmt.Println("recover 捕获到",err)   // recover 捕获到 异常A
            }
        }()
    
        panic("异常A")
        panic("异常B")
        panic("异常C")
    }
    
    1. 如果defer中也有终止异常的话,且defer前面也有终止异常的话 , 那么recover 只会捕获defer前面的
    • 案例
    package main
    
    import "fmt"
    
    func main() {
    
        defer func() {
            if err := recover(); err!=nil {
                fmt.Println("recover 捕获到",err)   // recover 捕获到 defer前的异常
            }
        }()
    
        panic("defer前的异常")
    
        defer func() {
            panic("defer中的异常")
        }()
    }
    
    1. 如果defer中也有异常, 且defer后也有异常抛出, 那么只会捕获defer中的异常
    • 案例
    package main
    
    import "fmt"
    
    func main() {
    
        defer func() {
            if err := recover(); err!=nil {
                fmt.Println("recover 捕获到",err)   // recover 捕获到 defer中的异常
            }
        }()
    
        defer func() {
            panic("defer中的异常")
        }()
    
        panic("defer后的异常")
    }
    

    相关文章

      网友评论

          本文标题:Go语言异常处理机制

          本文链接:https://www.haomeiwen.com/subject/krpvoftx.html