doutongya8378 2019-05-18 09:22
浏览 38
已采纳

为什么不正确地将非指针值调用的闭包添加到切片中?

This is the argument in go1.12.3 linux/amd64.

Added two closures to the slice s containing the function through the variable x. The closure is obtained by a method with a pointer receiver of type T. Added two closures to the slice s containing the function through the variable x. The closure is obtained by a method with a pointer receiver of type T.

package main

import "fmt"

type T struct {
    X int
}

func (t *T) f() func() {
    return func() { fmt.Println(t.X) }
}

func good() {
    s := []func(){}

    x := &T{1}
    s = append(s, x.f())

    x = &T{2}
    s = append(s, x.f())

    s[0]() // => 1
    s[1]() // => 2
}

func bad() {
    s := []func(){}

    x := T{1}
    s = append(s, (&x).f())  // Even if it rewrites to append(s, x.f()), the result is the same.

    x = T{2}
    s = append(s, (&x).f())

    s[0]() // => 2 WHY!?
    s[1]() // => 2
}

func main() {
    good()
    bad()
}

https://play.golang.org/p/j-818FZELQb

Of the above two functions, good() works as expected. In good s[0]() executes T{1}.f()(), and s s[1]() executes T{2}.f()(). However, bad() runs s[0]() and s[1]() run T{2}.f()(). Even though I added the element to the slice without overwriting it!

I have no idea what caused this behavior. Didn't the variable x have a value of type T instead of a pointer to a value of type T? Or do I not know the call specification of append?

Please give me some advice.

  • 写回答

1条回答 默认 最新

  • douzhi3454 2019-05-18 09:40
    关注

    Because in bad you have just one variable x of type T and one variable has just one address and thus your slice s contains always the same function working on the same variable which has value 2 when you start calling the functions.

    (In good you have two different variables of type T. You reuse a variable (x) of type *T but you still have two different T with different values.)

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?