Golang,指向具有值接收者的函数的函数指针,在第二次调用时不会使用更改后的接收者调用该函数

Golang, function pointer to function with value receiver, does not call that function with the changed receiver, when called for the second time

package main

import (
    "fmt"
)

type vector struct {
    x int
    y int
}

func (u vector) add(v vector) vector {
    fmt.Println("received: ", u)
    u.x += v.x
    u.y += v.y
    return u
}

func main() {
    vecA := vector{x: 5, y: 10}
    vecB := vector{x: 6, y: 7}

    fp := vecA.add // 1

    vecA = fp(vecB)   // 2
    fmt.Println(vecA)

    vecA = fp(vecB)   // 3
    fmt.Println(vecA)
}
/*
Output:
received:  {5 10}
{11 17}
received:  {5 10}
{11 17}
*/

在标记 1 处,我用 add 函数声明并初始化了 fp,使用 vecA 作为接收者。在标记 2 处,我更改了 vecA 的值。现在在 3,如果我们展开语句:fp(vecA),它变成:vecA.add(vecB)。现在我认为它应该使用 'changed' vecA 调用 add 函数(在标记 2 时更改),而不是 [=14= 的旧值](在标记 1),但它调用 add 函数与 'old' vecA(在标记 1),从输出中可以清楚地看出。 为什么?

尽管我找到了一种使用新 vecA 的方法,如下所示:

package main

import (
    "fmt"
)

type vector struct {
    x int
    y int
}

func (u *vector) add(v vector) {
    fmt.Println("received: ", *u)
    u.x += v.x
    u.y += v.y
}

func main() {
    vecA := &vector{x: 5, y: 10}
    vecB := vector{x: 6, y: 7}

    fp := vecA.add // 1

    fp(vecB)   // 2
    fmt.Println(*vecA)

    fp(vecB)   // 3
    fmt.Println(*vecA)
}
/*
Output:
received:  {5 10}
{11 17}
received:  {11 17}
{17 24}
*/

Now I think it should call add function with the 'changed' vecA

不对,这种想法是错误的。 fp 是并保持绑定到旧值。

在您的第一个示例中,fp 使用 vecA 的值,因此在初始分配后 vecA 发生的任何事情都不会反映在 fp 中。

在您的第二个示例中,fp 使用 vecA 的地址。现在您将内存位置中 vecA 的值传递给 add func(),以便它使用更新后的值。