go 異常處理panic和recover的簡(jiǎn)單實(shí)踐
panic 和 recover
當(dāng)然能觸發(fā)程序宕機(jī)退出的,也可以是我們自己,比如經(jīng)過(guò)檢查判斷,當(dāng)前環(huán)境無(wú)法達(dá)到我們程序進(jìn)行的預(yù)期條件時(shí)(比如一個(gè)服務(wù)指定監(jiān)聽(tīng)端口被其他程序占用),可以手動(dòng)觸發(fā) panic,讓程序退出停止運(yùn)行。
1. 觸發(fā)panic
手動(dòng)觸發(fā)宕機(jī),是非常簡(jiǎn)單的一件事,只需要調(diào)用 panic 這個(gè)內(nèi)置函數(shù)即可,就像這樣子
package main
func main() {
panic("crash")
}
運(yùn)行結(jié)果:
panic: crash
goroutine 1 [running]:
main.main()
d:/Goworks/src/尚硅谷/異常處理/demo01.go:4 +0x25
exit status 2
2. 捕獲 panic
發(fā)生了異常,有時(shí)候就得捕獲,就像 Python 中的except 一樣,那 Golang 中是如何做到的呢?
這就不得不引出另外一個(gè)內(nèi)建函數(shù) – recover,它可以讓程序在發(fā)生宕機(jī)后起生回生。
但是 recover 的使用,有一個(gè)條件,就是它必須在 defer 函數(shù)中才能生效,其他作用域下,它是不工作的。
這是一個(gè)簡(jiǎn)單的例子
package main
import "fmt"
func set_data(x int) {
defer func() {
// recover() 可以將捕獲到的panic信息打印
if err := recover(); err != nil {
fmt.Println(err)
}
}()
// 故意制造數(shù)組越界,觸發(fā) panic
var arr [10]int
arr[x] = 88
}
func main() {
set_data(20)
// 如果能執(zhí)行到這句,說(shuō)明panic被捕獲了
// 后續(xù)的程序能繼續(xù)運(yùn)行
fmt.Println("everything is ok")
}
運(yùn)行結(jié)果:
捕獲到panic后正常運(yùn)行。
runtime error: index out of range [20] with length 10 everything is ok
3. 無(wú)法跨協(xié)程
從上面的例子,可以看到,即使 panic 會(huì)導(dǎo)致整個(gè)程序退出,但在退出前,若有 defer 延遲函數(shù),還是得執(zhí)行完 defer 。
但是這個(gè) defer 在多個(gè)協(xié)程之間是沒(méi)有效果,在子協(xié)程里觸發(fā) panic,只能觸發(fā)自己協(xié)程內(nèi)的 defer,而不能調(diào)用 main 協(xié)程里的 defer 函數(shù)的。
來(lái)做個(gè)實(shí)驗(yàn)就知道了
package main
import (
"fmt"
"time"
)
func main() {
// 這個(gè) defer 并不會(huì)執(zhí)行
defer fmt.Println("in main")
go func() {
defer println("in goroutine")
// 這個(gè)panic就會(huì)終止程序
// 在這終止了外面的defer也不會(huì)執(zhí)行
panic("")
}()
time.Sleep(2 * time.Second)
}
輸出如下,并沒(méi)有執(zhí)行defer fmt.Println(“in main”)
in goroutine
panic:
goroutine 19 [running]:
main.main.func1()
d:/Goworks/src/尚硅谷/異常處理/demo03.go:14 +0x3e
created by main.main in goroutine 1
d:/Goworks/src/尚硅谷/異常處理/demo03.go:12 +0x59
exit status 2
4. 總結(jié)
Golang 異常的拋出與捕獲,依賴兩個(gè)內(nèi)置函數(shù):
- panic:拋出異常,使程序崩潰
- recover:捕獲異常,恢復(fù)程序或做收尾工作(通常來(lái)說(shuō),不應(yīng)該對(duì)進(jìn)入 panic 宕機(jī)的程序做任何處理,但有時(shí),需要我們可以從宕機(jī)中恢復(fù),至少我們可以在程序崩潰前,做一些操作,舉個(gè)例子,當(dāng) web 服務(wù)器遇到不可預(yù)料的嚴(yán)重問(wèn)題時(shí),在崩潰前應(yīng)該將所有的連接關(guān)閉,如果不做任何處理,會(huì)使得客戶端一直處于等待狀態(tài),如果 web 服務(wù)器還在開(kāi)發(fā)階段,服務(wù)器甚至可以將異常信息反饋到客戶端,幫助調(diào)試。)
revocer 調(diào)用后,拋出的 panic 將會(huì)在此處終結(jié),不會(huì)再外拋,但是 recover,并不能任意使用,它有強(qiáng)制要求,必須得在 defer 下才能發(fā)揮用途。
到此這篇關(guān)于go 異常處理panic和recover的簡(jiǎn)單實(shí)踐的文章就介紹到這了,更多相關(guān)go 異常處理panic和recover內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go 通過(guò)結(jié)構(gòu)struct實(shí)現(xiàn)接口interface的問(wèn)題
這篇文章主要介紹了Go 通過(guò)結(jié)構(gòu)struct實(shí)現(xiàn)接口interface的問(wèn)題,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-10-10
go goroutine 怎樣進(jìn)行錯(cuò)誤處理
在 Go 語(yǔ)言程序開(kāi)發(fā)中,goroutine 的使用是比較頻繁的,因此在日常編碼的時(shí)候 goroutine 里的錯(cuò)誤處理,怎么做會(huì)比較好呢,本文就來(lái)詳細(xì)介紹一下2021-07-07
Golang實(shí)現(xiàn)自己的Redis(有序集合跳表)實(shí)例探究
這篇文章主要為大家介紹了Golang實(shí)現(xiàn)自己的Redis(有序集合跳表)實(shí)例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01
詳解Go語(yǔ)言如何實(shí)現(xiàn)一個(gè)最簡(jiǎn)化的協(xié)程池
這篇文章主要為大家詳細(xì)介紹了Go語(yǔ)言如何實(shí)現(xiàn)一個(gè)最簡(jiǎn)化的協(xié)程池,文中的示例代碼講解詳細(xì),具有一定的參考價(jià)值,有需要的小伙伴可以了解一下2023-10-10
Go實(shí)現(xiàn)簡(jiǎn)單的數(shù)據(jù)庫(kù)表轉(zhuǎn)結(jié)構(gòu)體詳解
這篇文章主要為大家介紹了Go實(shí)現(xiàn)簡(jiǎn)單的數(shù)據(jù)庫(kù)表轉(zhuǎn)結(jié)構(gòu)體詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01

