golang的log.Fatal()和panic()函數的區別

來源:互聯網
上載者:User

golang的log.Fatal()和panic()函數的區別

在講兩者區別之前我們先看一下os.Exit()函數的定義:

func Exit(code int)Exit causes the current program to exit with the given status code.Conventionally, code zero indicates success, non-zero an error.The program terminates immediately; deferred functions are not run.

注意兩點:

  1. 應用程式馬上退出。
  2. defer函數不會執行。

再來看log.Fatal函數定義

func Fatal(v ...interface{})Fatal is equivalent to Print() followed by a call to os.Exit(1).

看原始碼:go/src/log/log.go

// Fatal is equivalent to l.Print() followed by a call to os.Exit(1).func (l *Logger) Fatal(v ...interface{}) {    l.Output(2, fmt.Sprint(v...))    os.Exit(1)}

總結起來log.Fatal函數完成:

  1. 列印輸出內容
  2. 退出應用程式
  3. defer函數不會執行

和os.Exit()相比多了第一步。

再來看內建函數panic()函數定義:

// The panic built-in function stops normal execution of the current// goroutine. When a function F calls panic, normal execution of F stops// immediately. Any functions whose execution was deferred by F are run in// the usual way, and then F returns to its caller. To the caller G, the// invocation of F then behaves like a call to panic, terminating G's// execution and running any deferred functions. This continues until all// functions in the executing goroutine have stopped, in reverse order. At// that point, the program is terminated and the error condition is reported,// including the value of the argument to panic. This termination sequence// is called panicking and can be controlled by the built-in function// recover.func panic(v interface{})

注意幾點:

  1. 函數立刻停止執行 (注意是函數本身,不是應用程式停止)
  2. defer函數被執行
  3. 返回給調用者(caller)
  4. 調用者函數假裝也收到了一個panic函數,從而
    4.1 立即停止執行當前函數
    4.2 它defer函數被執行
    4.3 返回給它的調用者(caller)
  5. ...(遞迴重複上述步驟,直到最上層函數)
    應用程式停止。
  6. panic的行為

簡單的總結panic()就有點類似java語言的exception的處理,因而panic的行為和java的exception處理行為就非常類似,行為結合catch,和final語句塊的處理流程。

下面給幾個例子:

例子1:log.Fatal

package mainimport (    "log")func foo() {    defer func () { log.Print("3333")} ()    log.Fatal("4444")}func main() {    log.Print("1111")    defer func () { log.Print("2222")} ()    foo()    log.Print("9999")}

運行結果:

$ go build && ./main2018/08/20 17:48:44 11112018/08/20 17:48:44 4444

可見defer函數的內容並沒有被執行,程式在log.Fatal(...)處直接就退出了。

例子2:panic()函數

package mainimport (    "log")func foo() {    defer func () { log.Print("3333")} ()    panic("4444")}func main() {    log.Print("1111")    defer func () { log.Print("2222")} ()    foo()    log.Print("9999")}

運行結果:

$ go build && ./main2018/08/20 17:49:28 11112018/08/20 17:49:28 33332018/08/20 17:49:28 2222panic: 4444goroutine 1 [running]:main.foo()        /home/.../main.go:9 +0x55main.main()        /home/.../main.go:15 +0x82

可見所有的defer都被調用到了,函數根據父子調用關係所有的defer都被調用直到最上層。
當然如果其中某一層函數定義了recover()功能,那麼panic會在那一層函數裡面被截獲,然後由recover()定義如何處理這個panic,是丟棄,還是向上再拋出。(是不是和exception的處理機制一模一樣呢?)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.