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)
?
Methods are fundamentally special and different from regular functions.
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.
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.
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.
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) {} // 'Foo' 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>0 {a--} // A while-do loop
for i := range channel {} // Receive values from a channel
for i:=0; i<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:
func f() {}
type F func(int) int
func (t T) SomeMethod() {}
{ ...; go func(){c<-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 (
.