iT邦幫忙

0

[Golang]恢復panic(recover、defer)-心智圖總結

1. 如何讓panic,包含一個值
在呼叫panic函數時,把某個值做為參數傳給該函數就可以了。panic函數的唯一一個參數是空接口(interface{})類型,也就是可以接受任何類型的值。但是,最好還是傳入error類型的錯誤值。如下面的範例。

package main

import (
	"errors"
	"fmt"
)

func main() {
    fmt.Println("Enter function main.")
    panic(errors.New("something wrong"))
    fmt.Println("Exit function main.") //不會被執行到,因為前一行發生panic
}

https://play.golang.org/p/aQ8eUyyBN1A

2. 正確使用recover函數
Go語言的內建函數recover,專門用於恢復panic。recover函數不用任何參數,並且會返回一個空接口類型的值。

什麼時候呼叫recover?
在panic發生之後? 不行,發生panic後,之後的程式碼都不會被執行到。
那放在panic之前呢? 也不行,因為呼叫recover函數時,並沒有發生panic,那麼recover函數就不會做任何事情,並且回傳nil。

這時候,就要用到defer語句了。defer語句的用途,延遲執行程式代碼。
延遲到什麼時候? 延遲到該defer語句的函數即將結束執行的時候。
因此,要恢復panic,需要聯合調用defer語句和recover函數。

package main

import (
  "errors"
  "fmt"
)

func main() {
  fmt.Println("Enter function main.")

  defer func() {
    fmt.Println("Enter defer function.")
    if p := recover(); p != nil {
      fmt.Printf("panic: %s\n", p)
    }
    fmt.Println("Exit defer function.")
  }()
  panic(errors.New("something wrong"))

  fmt.Println("Exit function main.")
}

https://play.golang.org/p/bJ20LIjtwDG

3. 函數中有多個defer語句,執行的順序是?
"defer函數的呼叫與其所屬的defer語句的執行順序完全相反"
也就是說,寫在最下面的defer函數會先被執行,其次,是寫在它上面的defer函數,而最上面的defer函數,會是最後才被呼叫。
在defer語句每次執行的時候,Go語言會把defer函數,儲存到一個Queue中,而這個Queue是FILO

package main

import "fmt"

func main() {
  defer fmt.Println("first defer")
  for i := 0; i < 3; i++ {
    defer fmt.Printf("defer in for [%d]\n", i)
  }
  defer fmt.Println("last defer")
}

https://play.golang.org/p/kvGq_JCfG3v

https://ithelp.ithome.com.tw/upload/images/20201105/20131728VGRQ1pHJuC.png

https://ithelp.ithome.com.tw/upload/images/20201105/20131728gBQ96p6Q8I.png

https://ithelp.ithome.com.tw/upload/images/20201105/20131728zEmVTDlhXq.png

參考來源:
郝林-Go语言核心36讲
https://github.com/hyper0x/Golang_Puzzlers


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言