2016-11-23 45 views
3

在godoc(https://blog.golang.org/defer-panic-and-recover),有一個例子:如何理解go語言中的`defer`?

  • 遞延功能可以讀取和分配給返回函數的命名返回值。
  • 在此示例中,延遲函數在周圍函數返回後遞增返回值i 。因此,該函數返回2:

    func c() (i int) { 
        defer func() { i++ }() 
        return i 
    } 
    

    我也寫了一個小編程':

    package main 
    
    import "fmt" 
    
    func b() int { 
        i := 0 
        for ; i < 4; i++ { 
         defer func() {fmt.Println(i); i++}() 
        } 
        return i 
    } 
    func main() { 
        fmt.Println("result = ", b()) 
    } 
    

    輸出爲:

    4 
    5 
    6 
    7 
    result = 4 
    

    所以我很困惑,爲什麼第二示例不輸出8

    +0

    退房,可能會有幫助:HTTPS: //blog.learngoprogramming。COM/golang-延遲簡化的-77d3b2b817ff –

    回答

    8

    請注意「可以讀取並分配給返回函數的命名的返回值」的部分。

    這意味着:

    func b() int { 
        var i int 
        defer func() { fmt.Println(i); i++ }() 
        return i 
    } 
    

    會說0result = 0,而:

    func b() (i int) { 
        defer func() { fmt.Println(i); i++ }() 
        return i 
    } 
    

    會說0result = 1

    這可能有助於想象,我的第一個例子中,return i分配i值到一個隱藏返回變量(因爲它未命名),然後繼續執行defer語句(只修改局部變量i)而在第二個示例中,我們直接指定給返回變量(因爲它的名稱),因此defer語句可以對其進行更改。

    基本上你的程序可以這樣解釋:

    package main 
    
    import "fmt" 
    
    func b() (hiddenVariable int) { 
        i := 0 
        for ; i < 4; i++ { 
         defer func() { fmt.Println(i); i++ }() 
        } 
        hiddenVariable = i; return // implicit meaning of return i 
    } 
    
    func main() { 
        fmt.Println("result = ", b()) 
    } 
    
    0

    僅僅根據我的瞭解,並推遲看着你的代碼後,我想說的是,對於循環推遲打印出來的隨後的「我是直到後來,然而,對於循環仍然運行,因此影響了‘我’由 FUNC b(),這是4

    for ; i < 4; i++ { 
        defer func() {fmt.Println(i); i++}() 
    } 
    return i 
    

    返回,因爲打印語句和它的‘價值’爲」我'被推遲,他們增加超過4,但'我'在for循環保持在4

    0

    A defer statement pushes a function call onto a list. The list of saved calls is executed after the surrounding function returns.FUNC B之後()在語義上等同於:

    func b() int { 
        i := 0 
        for ; i < 4; i++ { 
        } 
        ret := i 
        fmt.Println(i); i++ 
        fmt.Println(i); i++ 
        fmt.Println(i); i++ 
        fmt.Println(i); i++ 
        return ret 
    } 
    

    人機工程學B()返回4