Go语言方法语法的原理

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

Rationale for Go's method syntax

问题

好的,我必须承认,我并不经常使用Go,但我刚刚观察到了一些奇怪的东西,对于一个追求简洁和所有好东西的语言来说,这是很奇怪的。我会很惊讶如果这背后没有一个合理的理由,所以这就是我要找的。

所以当你有一个方法时,你像这样定义它:

func (s *SomeStruct) Foo(x int) { }

但为什么要为“接收器”多加一个参数列表呢?不直接这样做会更简单和更优雅:

func Foo(s *SomeStruct, x int) { }

然后将s.Foo(5)翻译成对函数Foo(s, 5)的调用,这样不是更好吗?

英文:

Ok, I have to admit, I don't really use Go very much at all, but I did just observe something that strikes me as odd for a language that strives for minimality and all that good stuff as Go does. I would be surprised if there isn't a legitimate rationale behind it, so that's what I'm looking for.

So when you have a method, you define it like this:

func (s *SomeStruct) Foo(x int) { }

but why have an extra parameter list just for the "receiver", as I think it's called? Would it not be a simpler and more elegant design to just do

func Foo(s *SomeStruct, x int) { }

and then have s.Foo(5) just be translated to a call to a function Foo(s, 5)?

答案1

得分: 20

方法在本质上与常规函数有所不同。

  • 方法必须与接收器类型位于同一个包中。
  • 方法用于满足接口。
  • 接收器参数是唯一可以重载的参数。
  • 当匿名结构字段具有方法时,这些方法被“继承”。

根据您的建议,函数和方法之间的界限变得非常模糊,很难解决上述问题。

话虽如此,我认为设计一种具有多方法和接口的语言将非常有趣。然而,那种语言不会是Go。

英文:

Methods are fundamentally special and different from regular functions.

  • Methods must live in the same package as the receiver type.
  • Methods are used to satisfy interfaces.
  • Receiver parameters are the only parameters which may be overloaded.
  • When anonymous struct fields have methods, those methods are "inherited".

With your proposal, the line between a function and a method becomes very blurry and it's difficult to figure out how to resolve the above issues.

That said, I think it would be really interesting to design a language with multimethods and interfaces. However, that language would not be Go.

答案2

得分: 7

你的问题正确指出了任何方法都是一个函数。然而,Go语言需要能够明确区分方法和函数。这是因为方法具有函数没有的特性。Foo是一个函数还是一个方法的选择需要由程序员来决定。

Go的极简主义意味着语言只定义了一小组关键字。Go的作者本可以选择一个新的关键字,比如method,来区分方法和函数:

method Foo(receiver *T, arg1 int) {}   // 'Foo'是一个方法,不是一个函数

在Go编程语言中,我们可以看到其哲学是重用已经存在的关键字,而不是为每个场合都有一个单独的关键字。for关键字就是这种方法的一个很好的例子:

for {}                     // 无限循环
for a>0 {a--}              // while-do循环
for i := range channel {}  // 从通道接收值
for i:=0; i<N; i++ {}      // C风格的for循环

基本思想是,对于解析器(和Go程序员)来说,为了区分各种类型的for循环,如果选项可以通过for关键字之后的语法来区分,就没有必要引入一个新的关键字:; := range identifier ...,它们的顺序和它们的存在/不存在。

func关键字遵循相同的模式。它可以在多个上下文中使用:

  • 函数定义:func f() {}
  • 函数类型:type F func(int) int
  • 方法定义:func (t T) SomeMethod() {}
  • 闭包:{ ...; go func(){c<-1}(); ...}

从极简主义的观点来看,一个单独的func关键字比多个关键字更简单、更优雅。

额外的接收者参数列表

func (t *T) Foo(x int) {}

使解析器能够区分方法和函数:

func IDENTIFIER ...     这将是一个函数
func ( ...              这将是一个方法

因此,解析器(以及Go程序员)可以根据func关键字后面是标识符还是(来进行区分。

英文:

Your question correctly points out that any method is a function. However, the Go language needs to be able to explicitly distinguish between methods and functions. The reason for this is that methods have features that functions do not have. The choice of whether Foo is a function or a method needs to be made by the programmer.

Go's minimalism means that the language defines only a small set of keywords. The Go authors could have chosen a new keyword, such as method, to distinguish methods from functions:

method Foo(receiver *T, arg1 int) {}   // &#39;Foo&#39; is a method, not a function

Looking around the Go programming language, we can see that the philosophy is to reuse already existing keywords rather than to have a separate keyword for each occasion. The for keyword is a good example of this approach:

for {}                     // Infinite loop
for a&gt;0 {a--}              // A while-do loop
for i := range channel {}  // Receive values from a channel
for i:=0; i&lt;N; i++ {}      // C-style for loop

The basic idea is that for the parser (and Go programmers) to distinguish the various types of for loops from each other, there is no need to introduce a new keyword if the options can be distinguished by the syntax of what comes after the for keyword: ; := range identifier ..., their sequential order, and their presence/absence.

The func keyword follows the same pattern. It can be used in multiple contexts:

  • function definitions: func f() {}
  • function types: type F func(int) int
  • method definitions: func (t T) SomeMethod() {}
  • closures: { ...; go func(){c&lt;-1}(); ...}

From minimalism viewpoint, a single func keyword is both simpler and more elegant than having multiple keywords.

The extra parameter list just for the receiver

func (t *T) Foo(x int) {}

enables the parser to distinguish methods and functions:

func IDENTIFIER ...     This is going to be a function
func ( ...              This is going to be a method

Thus, the parser (as well as Go programmers) can make the distinction based on whether the func keyword is followed by an identifier or by (.

答案3

得分: 3

提议的替代方案与当前状态在语义上并不完全相同,即它不仅仅是一种语法上的变化。它将[尝试]自动创建任何[本地包]类型的方法,该方法恰好是函数的第一个参数。考虑到方法集对于Go语言的自动接口满足规则的概念是多么基本,这很可能会导致一团糟。

简而言之,我认为对Go语言进行这样的改变没有任何改进,而且会破坏与方法和接口相关的许多好特性。

英文:

The proposed replacement is not semantically identical to the current state, i.e. it's not a syntactic change only. It will [attempt to] automagically create methods of any [local package] type that happens to be the first parameter of a function. Considering how fundamental method sets are wrt to Go's concept of automatic interface satisfaction rules, this will quite probably lead to a big big mess.

In short, I think such change to the Go language improves nothing while damaging a lot of it's nice features related to methods and interfaces.

答案4

得分: 1

可能是因为Go不是Python。

另外,因为以这种方式声明的函数不是方法。

你不能在对象包之外声明方法。所以我猜方法和函数之间的语法差异的主要原因是为了能够区分它们。

英文:

Probably because go isn't Python.

Also, because a function declared this way is not a method.

You cannot declare a method outside the object package. So I guess the main rationale in the syntax difference between methods and functions is to be able to differentiate them.

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

发表评论

匿名网友

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

确定