“defer”关键字传递的数据的引用

huangapple go评论83阅读模式
英文:

Data passed by reference to "defer"

问题

在《掌握Go并发》一书中有一段文字,让我觉得可能对于 "defer" 函数有所遗漏。

你还应该注意,任何通过引用传递的数据可能处于意外状态。

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

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

这段代码会打印出0,我认为是因为根据规范:

每次执行 "defer" 语句时,函数值和调用的参数会像平常一样被求值并重新保存。

也就是说,当调用 defer 时,*aValue 的值为0,这就是为什么最后打印出0的原因。在这种情况下,是否将指针传递给 defer 函数是无关紧要的。

我的理解正确吗?还是我有所遗漏?

英文:

There is a passage in the "Mastering Concurrency in Go" book which made me think I might be missing something about "defer" functions.

You should also take note that any data passed by reference may be in an unexpected state.

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

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

This prints 0, I thought, because according to spec:

> Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew

That is, *aValue is 0 when defer is called and that's why at the end it prints 0. Whether or not a pointer is passed to the differ function in this case is irrelevant.

Is my understanding correct or am I missing something?

答案1

得分: 3

考虑一个使用结构体的情况。

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)
}()
英文:

Consider a situation using structs.

type User struct {
    Name string
}

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

You know defer should run at the end, so you might expect to see User{Name: &quot;AJ&quot;} but instead you get User{Name: &quot;&quot;} because defer binds parameters.

If you use a pointer it works.

    user := &amp;User{}

If you use a closure, it works.

    defer func() {
        fmt.Printf(&quot;%#v\n&quot;, user)
    }()

答案2

得分: 2

defer语句是在“评估”参数并保存结果,而在defer调用时,评估*aValue的结果为0。你可能正在寻找类似这样的代码:

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

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

The defer statement is "evaluating" the parameters and saving the result, and the result of evaluating *aValue is 0 at the time of the defer call. Something like this may be what you're looking for:

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

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

huangapple
  • 本文由 发表于 2017年1月5日 02:53:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/41471236.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定