這陣子剛開始學習 Golang, 看了一些 tutorial, 發現有些範例會使用 log.Fatal()
輸出錯誤訊息,而有些會使用 panic()
, 這篇文章先記錄一下兩者的差別,後續的 Golang 筆記再慢慢補~
os.Exit()
在比較兩者差別之前,需要先了解 os.Exit()
的定義:
1 | func Exit(code int) |
- code == 0: success
- code != 0: error, program 會馬上終止,defer function 不會執行
log.Fatal()
Reference: Logger.Fatal
1 | func (l *Logger) Fatal(v ...any) |
1 | func (l *Logger) Fatal(v ...any) { |
在 source code 中可以看到 log.Fatal()
會先輸出錯誤訊息,接著 call os.Exit(1)
, 也就是會馬上終止 program, 並且不會執行 defer function.
Panic
Reference: buildin.go
1 | // The panic built-in function stops normal execution of the current |
- function F 會馬上終止
- defer function 被執行
- Return to caller G
- To the caller G, call F() 就像 call panic(), 因此進行:
- 終止 G 的執行
- 執行 defer functions
- Return to G’s caller
- 持續進行上個步驟,直到最上層的 function, 此時 program 會終止
以上整個流程叫做 panicking, 而可以透過 recover 來調控 panicking 的流程。
Recover
panic and recover 類似 C++/Java/Python 中的 try catch. recover 就是用來調控 panicking 流程,如果發生了 panic, 而我們需要做一些處理,就可以使用 recover()
, recover 必須在被 defer 的 function 中執行才有效果,如果在被 defer 的 function 外執行, recover 一定是回傳 nil
.
用法如下:
1 | package main |
Defer
上面提到的 defer
function 是指可以使用 defer
指定某個 function 延遲執行,會延遲到 main function return 之前再執行,for example:
1 | package main |
我們在 deferredFunc()
前加上 defer
,因此它會在 main()
return 前執行,所以執行結果會是先顯示 “Hello, world!”,才顯示 “deferredFunc”。
如果有多個 defer
functions, 在 main function return 前,會依 defer 的相反順序執行,也就是 LIFO.