golang面試基礎系列-defer(一)

go語言的語法學起來仍是比較快的,但在實戰過程當中總會遇到這樣或那樣的錯誤,逐個解決領悟以後,才能真正掌握go語言的細枝末節,成爲一名合格的gopherapp

廢話很少說,先吃幾個栗子:函數

  1. 下面的變量定義是否正確?
var a int, b int, c int
複製代碼
  1. 下面的寫法是否正確?
package main

s := "china"

func main() {

}
複製代碼
  1. 請寫出打印值:
s := make([]int, 5)

s = append(s, 1, 2, 3)

fmt.Println(s)
複製代碼

怎麼樣,是否是找到一丟丟感受了呀 : )ui

===============================spa

今天第一節(兒童節也闊以愉快的寫博客~),分享幾點defer的細枝末節:code

Defer規則一:下面的語句會觸發panic嗎?

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("觸發異常")

}
複製代碼

【解析】當 deferpanic 處於同一個 goroutine 中,defer 會試圖去recover(註釋部分),此時因爲沒有 recover 進行捕獲,所以會出現以下幾種輸出:orm

a. 

「觸發異常」

「打印後」

「打印中」

「打印前」



b. 

「打印後」

「打印中」

「打印前」

「觸發異常」



c. 

「打印後」

「觸發異常」

「打印中」

「打印前」
複製代碼

出現以上幾種不一樣的輸出結果,筆者的理解(歡迎討論~)是打印到 stdoutprint函數在同一時刻爭搶的結果,由於程序的實際執行順序是:遇到panic,先執行 deferfmt.Println 後,再輸出 panic 本身的報錯。cdn

Defer規則二:當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函數,所以輸出結果爲:博客

10 1 2 3
20 0 2 2
2 0 2 2
1 1 3 4
複製代碼

Defer規則三:能夠讀取有名返回值

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。string

以上就是今天分享的關於 defer 的幾個point,這些硬知識看書很容易忽略,在實戰中才能更好的掌握,keep moving~it

相關文章
相關標籤/搜索