Go使用指针接收器调用函数的语法

hap*_*s10 4 syntax pointers go

在Go中,如果我用指针定义一个函数作为接收器,它不应该只允许从指针调用函数吗?为什么可以从值本身调用此函数并具有相同的效果.

例如,在以下程序中:m1.reset()和m2.reset()具有相同的效果.即使m1是值,m2也是指针.

我有点困惑,因为有两种方法可以做同样的事情,我不确定应该遵循哪一种方法.虽然大多数代码遵循使用指针字段调用函数的约定.我错过了什么吗?

package main

    import "fmt"

    type MyStruct struct {
        X int
    }

    func (m *MyStruct) reset() {
        m.X = 0
    }

    func main() {
        m1 := MyStruct{1}
        m2 := &MyStruct{1}

        fmt.Println(m1.X)
        fmt.Println(m2.X)

        m1.reset()
        m2.reset()

        fmt.Println(m1.X)
        fmt.Println(m2.X)
    }
Run Code Online (Sandbox Code Playgroud)

jdi*_*jdi 10

@jnml提供了完美的doc规范说明,但我想添加一个基于你的代码示例.我认为你应该更少关注"为什么有两种方法可以做同样的事情",更多的是关于何时使用一种方法与另一种方式.具有指针作为接收器的方法具有修改该接收器的值的方法,而具有作为接收器的值的方法不能.这是因为方法接收接收器的副本.获得指针的副本后,仍可以修改其值.当您收到值的副本时,您在该方法中所做的更改只会更改副本,而不会更改原始副本:

package main

import "fmt"

type MyStruct struct {
    X int
}

func (m *MyStruct) resetPtr() {
    m.X = 0
}

func (m MyStruct) resetValue() {
    m.X = 0
}

func main() {
    m1 := MyStruct{1}
    m2 := &MyStruct{1}

    fmt.Println("Original Values:", m1.X, m2.X)

    m1.resetPtr()
    m2.resetPtr()

    fmt.Println("After resetPtr():", m1.X, m2.X)

    m1 = MyStruct{1}
    m2 = &MyStruct{1}

    m1.resetValue()
    m2.resetValue()

    fmt.Println("After resetValue():", m1.X, m2.X)
}
Run Code Online (Sandbox Code Playgroud)

产量

Original Values: 1 1
After resetPtr(): 0 0
After resetValue(): 1 1
Run Code Online (Sandbox Code Playgroud)

您可以看到访问这些变量的方式并不是真正的问题.它更多地是关于你可以在方法中使用它们做什么,以及它们如何作为参数传递给其他函数或方法(被复制).


zzz*_*zzz 5

规格

相应指针类型* T的方法集是接收者* T或T的所有方法的集(也就是说,它也包含T的方法集)。

关于方法调用的下一条必要信息如下:

x.m()如果x的方法集(类型)包含m并且参数列表可以分配给m的参数列表,则该方法调用有效。如果x是可寻址的并且&x的方法集包含m,x.m()则是x的简写(&x).m()

将以上两个内容放在一起,您将获得所看到的行为。