为什么在Golang中向结构体添加方法时必须声明一个变量名?

huangapple go评论161阅读模式
英文:

Why must we declare a variable name when adding a method to a struct in Golang?

问题

在给结构体添加方法时,为什么必须给它一个变量名,比如这里的 r

英文:

Let's say I have a struct

type Rectangle struct {
    length, width int
}

and I want to add a method to it:

func (r Rectangle) Area() int {
    return r.length * r.width
}

Why must I give it a variable name here r?

答案1

得分: 9

因为在Go语言中没有隐式标识符来表示实际的接收器值(类似于Java中的this),而且如果你想引用接收器值(Rectangle值)的字段或方法,你需要一个可以使用的标识符。

请注意,规范并不要求你给接收器值命名,例如,使用空白标识符的以下语法是有效的:

func (_ Rectangle) Foo() string {
    return "foo"
}

甚至可以省略接收器名称(参数名称):

func (Rectangle) Foo() string {
    return "foo"
}

规范中相关的部分是方法声明

MethodDecl   = "func" Receiver MethodName ( Function | Signature ) .
Receiver     = Parameters .

其中,Parameters 是:

Parameters     = "(" [ ParameterList [ "," ] ] ")" .
ParameterList  = ParameterDecl { "," ParameterDecl } .
ParameterDecl  = [ IdentifierList ] [ "..." ] Type .

正如你在最后一行中看到的,IdentifierList是可选的(但Type是必需的)。

英文:

Because there is no implicit identifier denoting the actual receiver value (like this in Java), and if you want to refer to the fields or methods of the receiver value (Rectangle value), you need an identifier that you can use.

Note that the spec does not require you to name the receiver value, e.g. the following using the blank identifier is a valid syntax:

func (_ Rectangle) Foo() string {
	return "foo"
}

Or even this: omitting the receiver name (the parameter name):

func (Rectangle) Foo() string {
	return "foo"
}

Relevant section from the spec: Method declarations:

> MethodDecl = "func" Receiver MethodName ( Function | Signature ) .
> Receiver = Parameters .

Where Parameters is:

> Parameters = "(" [ ParameterList [ "," ] ] ")" .
> ParameterList = ParameterDecl { "," ParameterDecl } .
> ParameterDecl = [ IdentifierList ] [ "..." ] Type .

As you can see in the last line, the IdentifierList is optional (but Type is required).

答案2

得分: 1

结构体方法类似于类方法。变量'r'是对应于应用该方法的结构体/类实例/对象的引用。如果没有这个引用,你将无法访问结构体/对象中的任何内容。

举个例子,假设我使用你的结构体创建了smallRectangle

var smallRectangle = Rectangle{5,3}

现在我想使用Rectangle方法Area来计算面积:

area := smallRectangle.Area()

让我们看看函数内部发生了什么。方法声明中的'r'成为了smallRectangle副本,因为它是调用它的结构体对象。

func (smallRectangle Rectangle) Area() int {
    return smallRectangle.length * smallRectangle.width
}

正如Icza所指出的,没有像selfthis这样的隐式标识符,所以方法访问结构体的值的唯一方式是通过标识符r

英文:

Struct methods are like Class methods. The variable 'r' is a reference to the struct/class instance/object that the method is being applied to. Without that reference, you will not be able to access whatever is contained within that struct/object.

Lets say for example, I created smallRectangle using your struct:

var smallRectangle = Rectangle{5,3}

Now I want to calculate the area using the Rectangle method Area

area := smallRectangle.Area()

Lets look at what happens within the function. r from the method declaration becomes a copy of smallRectangle since that's the struct object calling it.

func (smallRectangle Rectangle) Area() int {
    return smallRectangle.length * smallRectangle.width
}

As indicated by Icza, there is no implicit identifier like self or this, so the only way for the method to access the values of the struct is through the identifier r.

huangapple
  • 本文由 发表于 2016年3月22日 19:15:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/36152939.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定