go中可以拋出一個(gè)panic的異常琐鲁,然后在defer中通過recover捕獲這個(gè)異常毒坛,然后正常處理磺樱。
一砰蠢、go的defer
1.1 go defer 介紹
defer后邊會(huì)接一個(gè)函數(shù),但該函數(shù)不會(huì)立刻被執(zhí)行,而是等到包含它的程序返回時(shí)(包含它的函數(shù)執(zhí)行了return語句玖院、運(yùn)行到函數(shù)結(jié)尾自動(dòng)返回菠红、對(duì)應(yīng)的goroutine panic)defer函數(shù)才會(huì)被執(zhí)行。通常用于資源釋放难菌、打印日志途乃、異常捕獲等
1.2 多個(gè)go defer 的執(zhí)行順序
go的defer函數(shù),調(diào)用順序類似于
棧
扔傅,越后面的defer函數(shù)越先被執(zhí)行(后進(jìn)先出
)
func main() {
defer fmt.Printf("我")
defer fmt.Printf("是")
defer fmt.Printf("三")
defer fmt.Printf("火")
}
輸出結(jié)果:
火三是我
1.3 go defer 最佳實(shí)踐
? 推薦
import (
"fmt"
"io"
"os"
)
func main() {
// 打開文件
// fp, err := os.Open("./test.txt") // 只讀方式打開
fp, err := os.OpenFile("./test.txt", os.O_CREATE|os.O_APPEND, 6) // 讀寫方式打開
if err!=nil {
// 錯(cuò)誤處理
}
defer fp.Close() //如果成功打開了文件,就關(guān)閉文件烫饼,釋放資源猎塞。
doSomething(A) // 做了A事情
doSomething(B) // 做了B事情
doSomething(C) // 做了C事情
return
}
? 不推薦
import (
"fmt"
"io"
"os"
)
func main() {
// 打開文件
// fp, err := os.Open("./test.txt") // 只讀方式打開
fp, err := os.OpenFile("./test.txt", os.O_CREATE|os.O_APPEND, 6) // 讀寫方式打開
if err!=nil {
// 錯(cuò)誤處理
}
doSomething(A) // 做了A事情
doSomething(B) // 做了B事情
doSomething(C) // 做了C事情
defer fp.Close() //關(guān)閉文件,釋放資源杠纵。這里寫著寫著可能就忘了關(guān)了荠耽。
return
}
二、go panic
2.1 go panic 介紹
1比藻、內(nèi)建函數(shù)
2铝量、假如函數(shù)F中書寫了panic語句,會(huì)終止其后要執(zhí)行的代碼银亲,在panic所在函數(shù)F內(nèi)如果存在要執(zhí)行的defer函數(shù)列表慢叨,按照defer的逆序執(zhí)行
3、返回函數(shù)F的調(diào)用者G务蝠,在G中拍谐,調(diào)用函數(shù)F語句之后的代碼不會(huì)執(zhí)行,假如函數(shù)G中存在要執(zhí)行的defer函數(shù)列表馏段,按照defer的逆序執(zhí)行轩拨,這里的defer 有點(diǎn)類似 try-catch-finally 中的 finally
4、直到goroutine整個(gè)退出院喜,并報(bào)告錯(cuò)誤
三亡蓉、go recover
3.1 go recover 介紹
1、內(nèi)建函數(shù)
2喷舀、用來控制一個(gè)goroutine的panicking行為砍濒,捕獲panic,從而影響應(yīng)用的行為
3硫麻、一般的調(diào)用建議
a). 在defer函數(shù)中梯影,通過recever來終止一個(gè)gojroutine的panicking過程,從而恢復(fù)正常代碼的執(zhí)行
b). 可以獲取通過panic傳遞的error
3.2 go panic recover 最佳實(shí)踐
? 不推薦
// 使用error的寫法
func first() error {return nil}
func second() error {return nil}
func third() error {return nil}
func fourth() error {return nil}
func fifth() error {return nil}
func Do() error {
var err error
// 套娃
if err = first(); err == nil {
if err = second(); err == nil {
if err = third(); err == nil {
if err = fourth(); err == nil {
if err = fifth(); err == nil {
return nil
}
}
}
}
}
return err
}
? 推薦
// panic 寫法
func Do2() (err error) {
defer func(){
if r:= recover() ; r!= nil{
err = fmt.Errorf("Error: %+v", r)
}
}()
first2()
second2()
third2()
fourth2()
fifth2()
return
}