go語言的語法學起來仍是比較快的,但在實戰過程當中總會遇到這樣或那樣的錯誤,逐個解決領悟以後,才能真正掌握go語言的細枝末節,成爲一名合格的gopher
。app
廢話很少說,先吃幾個栗子:函數
var a int, b int, c int
package main s := "china" func main() { }
s := make([]int, 5) s = append(s, 1, 2, 3) fmt.Println(s)
怎麼樣,是否是找到一丟丟感受了呀 : )spa
===============================code
今天第一節(兒童節也闊以愉快的寫博客~),分享幾點defer
的細枝末節:rem
func main() { deferCall() } func deferCall() { defer func() { fmt.Println("打印前") /*if err := recover(); err != nil { fmt.Println(err) }*/ }() defer func() { fmt.Println("打印中") }() defer func() { fmt.Println("打印後") }() panic("觸發異常") }
【解析】當 defer
與 panic
處於同一個 goroutine
中,defer
會試圖去recover
(註釋部分),此時因爲沒有 recover
進行捕獲,所以會出現以下幾種輸出:博客
a. 「觸發異常」 「打印後」 「打印中」 「打印前」 b. 「打印後」 「打印中」 「打印前」 「觸發異常」 c. 「打印後」 「觸發異常」 「打印中」 「打印前」
出現以上幾種不一樣的輸出結果,筆者的理解(歡迎討論~)是打印到 stdout
的 print
函數在同一時刻爭搶的結果,由於程序的實際執行順序是:遇到panic
,先執行 defer
中 fmt.Println
後,再輸出 panic
本身的報錯。string
defer
被聲明時,其參數就會被實時解析func calc(index string, a, b int) int { ret := a + b fmt.Println(index, a, b, ret) return ret } func main() { a := 1 b := 2 defer calc("1", a, calc("10", a, b)) a = 0 defer calc("2", a, calc("20", a, b)) b = 1 }
【解析】當 defer 被調用時,a, b 會取當前實時解析值,並先計算defer
裏層 calc
的值保存下來,最後再執行defer
外層 calc
函數,所以輸出結果爲:it
10 1 2 3 20 0 2 2 2 0 2 2 1 1 3 4
package main import "fmt" func main() { v := c() fmt.Println(v) } func c() (i int) { defer func() { i++ }() return 1 }
【解析】當 defer
返回時,獲取到返回值 i = 1
,進行 defer
裏面的 i++
,因此返回輸出是2,而不是1。class
以上就是今天分享的關於 defer
的幾個point,這些硬知識看書很容易忽略,在實戰中才能更好的掌握,keep moving~import