Go语言异常处理机制

2018-09-29  本文已影响0人  超级皮波9

异常处理

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

fmt.Errorf(" 提示的内容 ")
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
}

异常恢复

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后的异常")
}
上一篇下一篇

猜你喜欢

热点阅读