golang panic、recover函式以及defer語句(1)
panic(執行時恐慌)
demo:
fmt.Println("Enter function caller2.") s1 := []int{0, 1, 2, 3, 4} e5 := s1[5]
1 panic: runtime error: index of range 2 3 goroutine 1 [running]: 4 main.main() 5 /User/zheng/Golang_Puzzlers/demo.go:5 +0x3d exit statu 2
這裡的第一行是“panic: runtime error: index out of range”。其中的“runtime error”的含義是,這是一個runtime程式碼包中丟擲的panic。在這個panic中,包含了一個runtime.Error介面型別的值。runtime.Error介面內嵌了error介面並做了一點點擴充套件,runtime包中有不少它的實現型別。
實際上,此詳情中的“panic: ”右邊的內容,正是這個panic包含的runtime.Error型別值的字串表示形式。
此外,panic詳情中一般還會包含與它的引發原因有關的goroutine的程式碼執行資訊。正如前述詳情中的“goroutine 1 [running]”,它表示有一個ID為1的goroutine在此panic被引發的時候正在執行。
注意,這裡的ID其實並不重要,因為它只是Go語言執行時系統內部給予的一個goroutine編號,我們在程式中是無法獲取和更改的。
我們再看下一行, “main.main()”表明了這個goroutine包裝的go函式就是命令原始碼檔案中的那個main函式,也就是說這裡的goroutine正是主goroutine。再下面的一行,指出的就是這個goroutine中的哪一行
程式碼在此panic被引發時正在執行。
這包含了此行程式碼在其所屬的原始碼檔案中的行數,以及這個原始碼檔案的絕對路徑。這一行最後的+0x3d代表的是:此行程式碼相對於其所屬函式的入口程式計數偏移量。不過,一般情況下它的使用者並不大。
最後, “exit status 2”表明我的這個程式是以退出狀態碼2結束執行的。在大多數作業系統中,只要退出狀態碼不是0,都意味著程式執行的非正常結束。在Go語言中,因panic導致程式結束執行的退出狀態碼一般都會是2。
從panic被引發到程式終止執行的大致過程是什麼?
某個函式中的某行程式碼有意或無意地引發了一個panic。這時,初始的panic詳情會被建立起來,並且該程式的控制權會立即從此行程式碼轉移至呼叫其所屬函式的那行程式碼上,也就是呼叫棧中的上一級。
這也意味著,此行程式碼所屬函式的執行隨即終止。緊接著,控制權並不會在此有片刻停留,它又會立即轉移至再上一級的呼叫程式碼處。控制權如此一級一級地沿著呼叫棧的反方向傳播至頂端,也就是我們編寫的最外層函式那裡。
這裡的外層函式指的就是go函式,對於主goroutine來說就是main函式。但是控制權也不會停留在那裡,而是被Go語言執行時系統收回。
隨後,程式崩潰並終止執行,承載程式這次執行的程序也會隨之死亡並消失。與此同時,在這個控制權傳播的過程中,panic詳情會被逐漸地積累和完善,並會在程式終止之前被打印出來。