2017-01-04 39 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

我知道这一点。谢谢。但这不是我的问题的答案。我想知道作者想指出什么。 –