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

在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)

    }



LEATH
浏览 227回答 3
3回答

慕姐4208626

规格说:对应的指针类型* T的方法集是接收者* T或T的所有方法的集(也就是说,它也包含T的方法集)。关于方法调用的下一条必要信息如下:x.m()如果x的方法集(类型)包含m并且参数列表可以分配给m的参数列表,则该方法调用有效。如果x是可寻址的并且&x的方法集包含m,x.m()则是x的简写(&x).m()。将以上两个内容放在一起,您将获得所看到的行为。

一只萌萌小番薯

提供了完美的文档规范说明,但我想基于您的示例添加一个代码示例。我认为您的重点应该放在“为什么有两种方法来做同一件事”上,而不是在何时使用一种方法与另一种方法上。具有指针作为接收者的方法具有修改该接收者的值的能力,而具有具有接收者的值的方法则不能修改。这是因为这些方法接收接收者的副本。当您获得一个指针的副本时,您仍然可以修改其值。当您收到该值的副本时,您在该方法中所做的更改只会更改副本,而不会更改原始副本:package mainimport "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)}输出Original Values: 1 1After resetPtr(): 0 0After resetValue(): 1 1您可以看到访问这些变量的方式并不是真正的问题。它的更多内容是您可以在方法内部使用它们做什么,以及如何将它们作为参数传递给其他函数或方法(正在复制)。

婷婷同学_

简短的解释是,幕后的Go编译器会自动转换:m1.reset() m2.reset()进入:(&m1).reset() m2.reset()
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go