新聞中心
Go語言的類型系統(tǒng)會在編譯時捕獲很多錯誤,但有些錯誤只能在運行時檢查,如數組訪問越界、空指針引用等,這些運行時錯誤會引起宕機。

宕機不是一件很好的事情,可能造成體驗停止、服務中斷,就像沒有人希望在取錢時遇到 ATM 機藍屏一樣,但是,如果在損失發(fā)生時,程序沒有因為宕機而停止,那么用戶將會付出更大的代價,這種代價可以是金錢、時間甚至生命,因此,宕機有時也是一種合理的止損方法。
一般而言,當宕機發(fā)生時,程序會中斷運行,并立即執(zhí)行在該 goroutine(可以先理解成線程)中被延遲的函數(defer 機制),隨后,程序崩潰并輸出日志信息,日志信息包括 panic value 和函數調用的堆棧跟蹤信息,panic value 通常是某種錯誤信息。
對于每個 goroutine,日志信息中都會有與之相對的,發(fā)生 panic 時的函數調用堆棧跟蹤信息,通常,我們不需要再次運行程序去定位問題,日志信息已經提供了足夠的診斷依據,因此,在我們填寫問題報告時,一般會將宕機和日志信息一并記錄。
雖然Go語言的 panic 機制類似于其他語言的異常,但 panic 的適用場景有一些不同,由于 panic 會引起程序的崩潰,因此 panic 一般用于嚴重錯誤,如程序內部的邏輯不一致。任何崩潰都表明了我們的代碼中可能存在漏洞,所以對于大部分漏洞,我們應該使用Go語言提供的錯誤機制,而不是 panic。
手動觸發(fā)宕機
Go語言可以在程序中手動觸發(fā)宕機,讓程序崩潰,這樣開發(fā)者可以及時地發(fā)現錯誤,同時減少可能的損失。
Go語言程序在宕機時,會將堆棧和 goroutine 信息輸出到控制臺,所以宕機也可以方便地知曉發(fā)生錯誤的位置,那么我們要如何觸發(fā)宕機呢,示例代碼如下所示:
package main
func main() {
panic("crash")
}代碼運行崩潰并輸出如下:
panic: crash
goroutine 1 [running]:
main.main()
D:/code/main.go:4 +0x40
exit status 2
以上代碼中只用了一個內建的函數 panic() 就可以造成崩潰,panic() 的聲明如下:
func panic(v interface{}) //panic() 的參數可以是任意類型的。
在運行依賴的必備資源缺失時主動觸發(fā)宕機
regexp 是Go語言的正則表達式包,正則表達式需要編譯后才能使用,而且編譯必須是成功的,表示正則表達式可用。
編譯正則表達式函數有兩種,具體如下:
1) func Compile(expr string) (*Regexp, error)
編譯正則表達式,發(fā)生錯誤時返回編譯錯誤同時返回 Regexp 為 nil,該函數適用于在編譯錯誤時獲得編譯錯誤進行處理,同時繼續(xù)后續(xù)執(zhí)行的環(huán)境。
2) func MustCompile(str string) *Regexp
當編譯正則表達式發(fā)生錯誤時,使用 panic 觸發(fā)宕機,該函數適用于直接使用正則表達式而無須處理正則表達式錯誤的情況。
MustCompile 的代碼如下:
func MustCompile(str string) *Regexp {
regexp, error := Compile(str)
if error != nil {
panic(`regexp: Compile(` + quote(str) + `): ` + error.Error())
}
return regexp
}代碼說明如下:
- 第 1 行,編譯正則表達式函數入口,輸入包含正則表達式的字符串,返回正則表達式對象。
- 第 2 行,Compile() 是編譯正則表達式的入口函數,該函數返回編譯好的正則表達式對象和錯誤。
- 第 3 和第 4 行判斷如果有錯,則使用 panic() 觸發(fā)宕機。
- 第 6 行,沒有錯誤時返回正則表達式對象。
手動宕機進行報錯的方式不是一種偷懶的方式,反而能迅速報錯,終止程序繼續(xù)運行,防止更大的錯誤產生,不過,如果任何錯誤都使用宕機處理,也不是一種良好的設計習慣,因此應根據需要來決定是否使用宕機進行報錯。
在宕機時觸發(fā)延遲執(zhí)行語句
當 panic() 觸發(fā)的宕機發(fā)生時,panic() 后面的代碼將不會被運行,但是在 panic() 函數前面已經運行過的 defer 語句依然會在宕機發(fā)生時發(fā)生作用,參考下面代碼:
package main
import "fmt"
func main() {
defer fmt.Println("宕機后要做的事情1")
defer fmt.Println("宕機后要做的事情2")
panic("宕機")
}代碼輸出如下:
宕機后要做的事情2
宕機后要做的事情1
panic: 宕機
goroutine 1 [running]:
main.main()
D:/code/main.go:8 +0xf8
exit status 2
對代碼的說明:
- 第 6 行和第 7 行使用 defer 語句延遲了 2 個語句。
- 第 8 行發(fā)生宕機。
宕機前,defer 語句會被優(yōu)先執(zhí)行,由于第 7 行的 defer 后執(zhí)行,因此會在宕機前,這個 defer 會優(yōu)先處理,隨后才是第 6 行的 defer 對應的語句,這個特性可以用來在宕機發(fā)生前進行宕機信息處理。
網站題目:創(chuàng)新互聯(lián)GO教程:Go語言宕機(panic)——程序終止運行
網頁路徑:http://m.fisionsoft.com.cn/article/dhscddp.html


咨詢
建站咨詢
