参数和接收器之间有什么区别?

21

我正在学习Go语言的教程,但是遇到了一个我无法理解的方法签名,希望得到帮助:

func (p *Page) save() error {
    filename := p.Title + ".txt"
    return ioutil.WriteFile(filename, p.Body, 0600)
}

文档中这样解释:

该方法的签名为:"这是一个名为 save 的方法,将 p 作为接收器,它是指向 Page 的指针。它不需要参数,并返回类型为 error 的值。"

我无法理解接收器(receiver)是什么。如果我把它看作参数,那么我会期望在 save() 中有一个参数。


4
如果您熟悉C ++、Java或JavaScript,则“接收器”相当于this。如果您熟悉Perl或Python,则相当于方法的第一个参数(通常在Python代码中为self)。如果您不熟悉其中任何一种语言,那么...您熟悉其他面向对象的语言吗? - ruakh
1
语法对我来说非常困惑。我使用PHP和Python。那么Go没有类吗? - Marty Wallace
Go语言没有类。接收器是指向Page的指针 - 可能是您已初始化并想要执行某些操作的结构体(在这种情况下,似乎是将Page的Body保存到与Page标题相同的文件中)。您无法在不属于Page类型的对象上使用此函数。 - cbll
2个回答

30

接收器只是参数的一个特殊情况。Go语言提供了语法糖,通过将第一个参数声明为接收器来附加方法到类型上。

例如:

func (p *Page) save() error

阅读 "将名为save的函数附加到类型*Page,并使其返回error",而不是声明:

func save(p *Page) error

声明一个名为save的函数,它接受一个类型为*Page的参数并返回一个error

作为其只是语法糖的证明,您可以尝试以下代码:

p := new(Page)
p.save()
(*Page).save(p)

最后两行代码表示完全相同的方法调用。

此外,请阅读这个回答


出于好奇,为什么这种方法比将方法封装在类中并像class->func一样调用方法而不必传递类型更可取?我现在明白它在做什么,但不知道为什么?例如,在Java中,您只需执行p->save(),而无需传递对象。(也许这是另一个问题!!) - Marty Wallace
4
Go语言中没有类(classes),只有类型(types)。但你也可以问同样的问题在Java中。假设你可以将Java类中的所有方法取出,通过显式传递this参数来过程化地调用它们,那么就是同样的情况。 - thwd

13

那么这就像方法所属的上下文? - Marty Wallace
1
没错。正如ruakh所说,它类似于c++中的'this'。它是当前对象或指向当前对象的指针(取决于您是否放置了'*')。 - creack

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接