Golang,指向带有值接收器的函数的函数指针,第二次调用时不与更改的接收器一起调用该函数

问题描述 投票:0回答:1
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,我使用fp作为接收者,通过add函数声明并初始化了vecA。在标记2时,我更改了vecA的值。现在在3,如果我们扩展语句:fp(vecA),则变为:vecA.add(vecB)。现在,我认为它应使用“已更改” add(在标记2处更改)而不是vecA的旧值(在标记1处)调用vecA函数,但它正在调用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}
*/
go function-pointers receiver
1个回答
0
投票

行为上的差异与函数指针无关。

区别在于,在一种情况下,目标是值func (u vector),在另一种情况下,目标是指向值func (u *vector)的指针。

当目标u是一个值时,我们将获得该值的副本。修改u就是修改在函数执行结束时丢弃的副本。

当目标u是指向该值的指针时,将修改原始值。

因此,如果函数add需要修改目标值u,则目标必须是指向该值的指针。

© www.soinside.com 2019 - 2024. All rights reserved.