2017-01-04 40 views
0

在「掌握併發在去」書中有一段話讓我覺得我可能會錯過關於「延遲」功能的東西。通過引用傳遞數據「推遲」

您還應該注意,通過引用傳遞的任何數據可能處於意外狀態。

func main() { 
    aValue := new(int) 
    defer fmt.Println(*aValue) 

    for i := 0; i < 100; i++ { 
     *aValue++ 
    } 
} 

這將打印0,我想,因爲,按照規範:

每一次「推遲」執行語句,函數值和參數的號召被照常評估,重新保存

也就是說,* aValue在調用defer時是0,這就是爲什麼在最後打印0.在這種情況下是否將指針傳遞給不同的函數是ir相關。

我的理解是正確的還是我錯過了什麼?

+5

我不明白它在說什麼。 Go書中的「通過引用傳遞」這個短語也很奇怪,因爲Go中的所有值都是按值傳遞的。 – JimB

+0

那麼,這個例子就是傳遞一個指針。我認爲這是他通過參考傳遞的意思。因爲雖然指針被複制,但副本仍然指向相同的內存。 –

+4

該示例沒有在任何地方傳遞指針,它取消引用指針並傳遞int值(和「傳遞引用」具有與「傳遞指針值」不同的含義) – JimB

回答

2

考慮使用結構的情況。

type User struct { 
    Name string 
} 

func main() { 
    user := User{} 
    defer fmt.Printf("%#v\n", user) 
    user.Name = "AJ" 
} 

你知道defer應該在結束時運行,所以你可能會看到User{Name: "AJ"}而是你User{Name: ""}因爲defer結合參數。

如果你使用它的指針,它的工作原理。

user := &User{} 

如果您使用閉包,它可以工作。

defer func() { 
     fmt.Printf("%#v\n", user) 
    }() 
+0

儘管這解釋了我在問題中已經提到的內容(如何評估參數),但是使用struct指出了作者可能試圖說出的內容。 –

+0

還有一些其他延期問題。被調用函數的引用被保存。所有參數都會被評估和保存(所以如果您將其他函數調用作爲參數,它們將在執行後立即執行)。 –

1

推遲語句是「評估」參數並保存結果,在延遲調用時評估*aValue的結果爲0。像這樣的東西可能是你要找的東西:

func main() { 
    aValue := new(int) 
    defer func() { fmt.Println(*aValue) }() 

    for i := 0; i < 100; i++ { 
     *aValue++ 
    } 
} 
+0

我知道這一點。謝謝。但這不是我的問題的答案。我想知道作者想指出什麼。 –