Golang的异常处理实战篇
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
Go语言的异常捕获要比Python中简单的多,它没有Python中那么多复杂的异常类型及继承体系。接下来我们来一起体验一下Golang的异常处理。
一.代码运行时出错应该怎样处理呢?
1>.算数除零异常案例
package main import ( "fmt" ) func main() { //定义除数 a := 20 //定义被除数 b := 0 //除数不能为0,编译时并不会报错,但是在代码运行时会报错哟~ c := a / b //由于上面的代码执行报错啦,该行代码不会被执行 fmt.Printf(" %d ➗ %d = %d ", a, b, c) }
2>.数组索引越界异常案例
package main import ( "fmt" ) func myArr(index int) { //定义数组 var arr [10]int //数组这里赋值时可能会存在一个风险,即索引越界异常 arr[index] = 123 fmt.Println(arr) } func main() { myArr(12) }
二.Go语言中自定义异常接口
1>.使用errors自定义异常消息(并不会使得程序崩溃)
package main import ( "errors" "fmt" ) func div(x int, y int) (res int, err error) { if y == 0 { /* Go语言引入了一个关于错误处理的标准模式,即error接口,该接口需要导入"errors"包: errors接口适合返回可控的错误,即我们知道在某个代码块中可能会出现的异常。 */ err = errors.New("div函数除零异常...") return } res = x / y return } func main() { a := 10 b := 0 /* res: 用来接收运算结果 err: 用来接收错误消息 nil: 表示空,"if err != nil"表示变量err接收的错误消息是否为空。 */ res, err := div(a, b) if err != nil { fmt.Println(err) //log.Fatal(err) //我们也可以使用log包来帮助咱们输出错误,它会在错误消息签名自动加上日期时间 } else { fmt.Println(res) } fmt.Println("代码执行完毕") }
2>.使用panic自定义异常消息(程序会崩溃)
package main import ( "fmt" ) func myArr2(index int) { //定义数组 var arr [10]int if index >= 10 { /* panic函数与errors接口不同: (1)使用panic时无需导入包; (2)若出现异常,使用panic封装异常消息时,会直接导致程序运行结束,换句话说,error是一般性错误,而panic函数返回的是让程序崩溃的错误 温馨提示: 一般而言,当panic异常发生时,程序会中断运行。随后,程序崩溃并输出日志消息。日志信息包括panic value和函数调用的堆栈跟踪信息 当然,如果直接调用内置的panic函数也会引发panic异常,panic函数接收任何值作为参数。 */ panic("请注意,index > 10,出现了索引越界异常...(index的取值范围0~9)") } //上面使用了panic接口封装了异常处理错误,因此如果代码到这一行说明没有索引越界异常 arr[index] = 123 fmt.Println(arr) } func main() { myArr2(12) fmt.Println("代码执行完毕") }
三.使用recover进行异常捕获
1>.defer延迟调用
package main import ( "fmt" ) func main() { /* defer语句被用于预定对一个函数的调用。可以把这类被defer语句调用的函数称为函数。 defer的应用场景: (1)释放占用的资源; (2)捕获异常处理 (3)输出日志 温馨提示: 如果一个函数中有多个defer语句,它们会以LIFO(后进先出)的顺序执行。 先不要运行代码,你先猜猜下面的代码的执行顺序。 */ defer fmt.Println(" https://www.cnblogs.com/yinzhengjie/") fmt.Println("我的名字叫尹正杰,英文名叫'Jason Yin'.爱好开源技术.") defer fmt.Println(" https://www.cnblogs.com/yinzhengjie2020") fmt.Println("我的博客是:") }
2>.defer结合recover进行错误拦截
package main import "fmt" func test3(index int) { /* 错误拦截要在产生错误前设置,因此建议大家把错误拦截的函数放在函数内部的首行定义。 */ defer func() { /* 运行时panic异常一旦被引发就会导致程序崩溃 Go语言提供了专用于"拦截"运行时panic的内建函数"recover"。 它可以使当前的程序从运行时panic的状态中恢复并重新获得流程控制权,欢聚话说,通过recover进行不可控的错误拦截,重新获取程序的控制权 */ err := recover() if err != nil { fmt.Println(err) } }() /* 定义容量为10的数组 */ var arr [10]int if index >= 10 { panic("请注意,index > 10,出现了索引越界异常...(index的取值范围0~9)") } arr[index] = 123 fmt.Println(arr) } func main() { test3(5) test3(12) fmt.Println("代码执行完毕") }
3>.面试题(请根据下面代码手写出输出结果)
package main import ( "fmt" ) func f1() (int, error) { defer fmt.Println(1) defer fmt.Println(2) fmt.Println(3) return fmt.Println(4) } func f2() (int, error) { defer fmt.Println(5) defer fmt.Println(6) fmt.Println(7) f1() defer func() (int, error) { defer fmt.Println(8) fmt.Println(9) return fmt.Println(10) }() return fmt.Println(11) } func main() { f2() }