go语言defer,panic,recover 与错误处理
三个关键字
defer:在函数中,经常要打开资源(如:文件打开,数据库连接等),为了在函数执行后,及时释放资源,go的设计者提供defer(延时机制)
panic:内置函数,接收一个interface{}类型的值(也就是任何值)作为参数,可接收error类型的变量,输出错误信息,并退出程序。
errors.New("错误说明"):返回一个error类型的值,表示一个错误
recover:内置函数,可以捕获到go中的异常
defer的单独使用
package main import ( "fmt" ) func deferTest() int{ defer fmt.Println("aaaaaaaaaaaaaaaaa") // 先不执行,知道函数执行完成后执行该语句;如果前面有一语句为打开数据库,那么我们可以立刻在该语句后使用defer修饰关闭数据库代码,而不影响函数中间的代码执行,避免后续忘记关闭数据库 fmt.Println("bbbbbbbbbbbbbbbbb") return 2 } func main(){ fmt.Println("deferTest:",deferTest()) }
defer 关键字修饰的语句会被压入一个栈,且不会执行该语句;当函数执行完成后,按照先进后出的方式,执行defer压入栈中的语句。
因此执行结果如下:
bbbbbbbbbbbbbbbbb aaaaaaaaaaaaaaaaa deferTest: 2
defer、panic、recover组成的错误处理
go语言不支持 try...catch...finally,取而代之的是 defer、panic、revocer组合
例子一
看以下代码:
package main import ( "fmt" ) func deferTest2(){ var num1 int8 = 10 var num2 int8 = 0 fmt.Println("函数内部代码") fmt.Println(num1 / num2) // 在这里程序 panic了,因此在该位置退出,且程序不会执行后面的代码 } func main(){ deferTest2() fmt.Println("后面的代码...") }
运行结果如下:
使用 defer ,revocer 进行错误处理后,任然可以执行后面的代码,因此修改代码如下:
package main import ( "fmt" ) func deferTest2(){ defer func(){ // 函数发生异常后会执行 defer里的代码,并且不会退出程序 err := recover() if err != nil { fmt.Println("发生异常:",err) } }() var num1 int8 = 10 var num2 int8 = 0 fmt.Println("函数内部代码") fmt.Println(num1 / num2) } func main(){ deferTest2() fmt.Println("后面的代码...") }
执行结果如下:
例子二,自定义错误,使用panic 输出错误程序后,退出程序
package main import ( "fmt" "errors" ) func myError(a string) (err error){ if a == "a" { return nil } return errors.New("这是一个自定义错误") } func doMyError(){ err := myError("b") if err != nil { // 如果有错误,则打印错误,并退出程序 panic(err) } fmt.Println("继续向后执行...") } func main(){ doMyError() fmt.Println("后面的代码...") }
执行结果为:
当 myError 传 a的时候,执行结果如下:
我们再上面代码加入defer语句处理错误后:
import ( "fmt" "errors" ) func myError(a string) (err error){ if a == "a" { return nil } return errors.New("这是一个自定义错误") } func doMyError(){ defer func(){ err := recover() if err != nil { fmt.Println("出现的error为:",err) } }() err := myError("b") if err != nil { panic(err) // 发生panic 后,执行压入栈的defer语句,且程序不会终止 } fmt.Println("继续向后执行...") // 发生panic 后不会执行该语句 } func main(){ doMyError() fmt.Println("后面的代码...") }
执行结果为:
博客里大都是转载的内容,其目的主要用户知识的组织和管理。