不管使用什么語言寫的程序都會有異常少孝,這其中包括系統(tǒng)異常以及業(yè)務(wù)異常。
當(dāng)業(yè)務(wù)邏輯校驗錯誤的時候需要拋出一個業(yè)務(wù)異常溺忧。返回前臺一個比較有好的信息
如果存在一些不確定的異常我們應(yīng)該捕獲,并且執(zhí)行對應(yīng)的邏輯。其他語言中有try catch 那么go語言怎么來實現(xiàn)呢
下面我們先看一下go中的異常
拋出異常很簡單,只需要 panic 一下争剿,這個方法會終止程序
go中定義異常有兩種方式,一種是errors.New()痊末、另一種是定義一個結(jié)構(gòu)體實現(xiàn)Error方法
下面我們來使用一下
func main() {
panic(errors.New("服務(wù)器異常"))
fmt.Println("執(zhí)行業(yè)務(wù)")
}
報錯
panic: 服務(wù)器異常
goroutine 1 [running]:
main.main()
/Users/wendell/GolandProjects/blog/error.go:50 +0x2c
大部分情況下蚕苇,我們不希望報錯的時候?qū)⒊绦蚪K止,可以使用 defer 與 recover 來捕獲異常
defer 不管業(yè)務(wù)正常結(jié)束還是拋出錯誤凿叠,在方法執(zhí)行結(jié)束時會執(zhí)行 defer 后面定義的函數(shù)
recover 捕獲異常
func main() {
defer func() {
if err := recover(); err != nil {
fmt.Println("捕獲異常", err)
}
}()
panic(errors.New("服務(wù)器異常"))
fmt.Println("執(zhí)行業(yè)務(wù)")
}
執(zhí)行結(jié)果
捕獲異常 服務(wù)器異常
雖然捕獲到了異常涩笤,程序沒有因為異常而終止,但是卻沒有執(zhí)行后面的業(yè)務(wù)盒件,如果要保護后續(xù)代碼執(zhí)行蹬碧,要怎么做呢
上面說到 defer 是在方法結(jié)束時執(zhí)行,那么只需要上面報錯與捕獲邏輯不在一個方法內(nèi)就可以了炒刁,于是使用匿名函數(shù)重構(gòu)
func main() {
func() {
defer func() {
if err := recover(); err != nil {
fmt.Println("捕獲異常", err)
}
}()
panic(errors.New("服務(wù)器異常"))
}()
fmt.Println("執(zhí)行業(yè)務(wù)")
}
執(zhí)行
捕獲異常 服務(wù)器異常
執(zhí)行業(yè)務(wù)
雖然現(xiàn)在達(dá)到了效果恩沽,但是如果業(yè)務(wù)中有許多這樣的地方,都要這么寫也挺麻煩翔始。那么有沒有像其它語言中try catch來處理呢
可以將 try 中的邏輯當(dāng)作一個函數(shù)罗心,catch 中的邏輯當(dāng)作一個函數(shù),如果有報錯執(zhí)行 catch 函數(shù)城瞎,于是封裝一個方法
func try(tryFunc func(), catchFunc func(interface{})) {
defer func() {
if err := recover(); err != nil {
catchFunc(err)
}
}()
tryFunc()
}
重構(gòu)代碼
func main() {
try(func() {
panic(errors.New("服務(wù)器異常"))
}, func(err interface{}) {
fmt.Println("捕獲異常", err)
})
fmt.Println("執(zhí)行業(yè)務(wù)")
}
執(zhí)行
捕獲異常 服務(wù)器異常
執(zhí)行業(yè)務(wù)
到這一個簡單的try catch就寫完了渤闷。
歡迎關(guān)注,學(xué)習(xí)不迷路全谤!