package main
import (
"errors"
"fmt"
)
/* Golang语言函数详解之内置函数panic、recover的基本使用和defer、panic、recover结合使用进行异常处理 */
/*
defer、panic、recover 的使用规则记住下面三点:
1. recover()函数必须搭配defer一块使用。
2. defer 一定要在可能引发panic的语句之前定义。
3. panic() 可以在任何地方使用。
内置函数 : 作用
close 主要用来关闭channel
len 用来求长度,比如string、array、slice、map、channel
new 用来分配内存,主要用来分配值类型,比如int、struct。返回的是指针
make 用来分配内存,主要用来分配引用类型,比如chan、map、slice
append 用来追加元素到数组、slice中
panic和recover 用来做错误处理
Go 语言中目前Go1.12是没有异常机制,但是使用panic/recover模式来处理错误。panic可以在任何地方引发,但recover只有在defer调用的函数中有效。
首先来看一个例子:
1. panic()函数 的基本使用
2. recover()函数 的基本使用
3. defer、recover 实现异常处理
4. defer、panic、recover 抛出异常
*/
func funcA() {
fmt.Println("func A")
}
func funcB() {
panic("panic in B")
}
func funcC() {
fmt.Println("func C")
}
// defer、panic、recover 三者结合使用处理异常
func funcD() {
defer func() {
err := recover()
// 如果程序出现了panic错误,可以通过recover恢复过来
if err != nil {
fmt.Println("execute this recover in D")
}
}()
panic("panic in D")
}
// 3. defer、recover 实现异常处理
func fntwo() {
defer func() {
err := recover() // 下面的除法运算有分母为0的异常,此处结合recover函数,实现异常处理,不会让程序崩掉。
if err != nil {
fmt.Println("抛出异常给管理员发送邮件") // 这个会执行
fmt.Println(err) // 会把捕获到的异常原因在此处打印,原因是 runtime error:integer divide by zero
}
}()
num1 := 10
num2 := 0
res := num1 / num2
fmt.Println("look this res=", res) // 这个地方分母为0,不符合要求,是一个异常。res := num1 / num2报错,此处不会执行,程序会跳转到上面的defer func(){}()函数定义那里
}
// 4. defer、panic、recover 三者结合使用处理异常
func readFileName(fileName string) error {
if fileName == "main.go" {
return nil
}
return errors.New("读取文件错误")
}
func fn3() {
// 这里面和上面的funcD()函数中defer、recover、panic用法相同,funcD是流水线代码,理解起来更直观。
defer func() {
err := recover()
if err != nil {
fmt.Println("犯错啦,就要给你的上司发送邮件督促你啦")
}
}()
var err = readFileName("niriliya.go")
// 调用这个函数入参不符合if条件,会返回erros.New(“读取文件错误”),另外这个erros.New()函数的返回值查看源码可知只有一个参数来接收
// 下面的if条件成立,会执行
if err != nil {
panic(err) // 这里用panic + 上面的 recover 来做readFileName()函数的错误处理。
}
fmt.Println("继续执行吧,皮卡丘")
}
func main() {
// 1. panic()函数的基本使用
funcA()
//funcB()
funcC()
/* 执行结果是:
func A
panic: panic in B
goroutine 1 [running]:
main.funcB(...)
C:/Users/Zhaoshan.lu/go/DaDi/15.go:24
main.main()
C:/Users/Zhaoshan.lu/go/DaDi/15.go:34 +0x66
exit status 2
注意:我们在funcB()函数中加了panic()导致程序崩溃,异常退出了。这个时候我们就可以通过recover()将程序恢复回来,继续往后执行。
*/
// 2. recover()函数的基本使用
// 注意这个规则: 【【 panic可以在任何地方引发,但recover只有在defer调用的函数中有效。 】】
funcD() // 执行这个的时候,先注释一下上面的funcB()函数,因为funcB()函数有panic异常会直接结束程序的运行就走不到这里,看不到效果了。
fmt.Println()
/* 执行结果是:
func A
func C
execute this recover in D
注意下面两个固定的规则:
1. recover()必须搭配在defer调用的函数中使用。
2. defer 一定要在可能引发panic的语句之前定义。
*/
// 3. defer、recover 实现异常处理
fntwo()
fmt.Println()
/* 执行结果是:
func A
func C
execute this recover in D
抛出异常给管理员发送邮件
runtime error: integer divide by zero
*/
// 4. defer、panic、recover 抛出异常
fn3()
fmt.Println()
/* 执行结果是:
func A
func C
execute this recover in D
抛出异常给管理员发送邮件
runtime error: integer divide by zero
犯错啦,就要给你的上司发送邮件督促你啦
*/
}