I have seen a fair amount of blogs & videos on Go and as far as I recall, none of the authors use 'self' or 'this' for the receiver variable when writing methods. However there seems to be a number of questions on stack overflow that do this, and it got me thinking about if this is misleading to name the variable 'self'?
Reading the Spec for Method Sets does not provide any evidence either way (in my interpretation).
I seem to recall finding somewhere that it was not really a self pointer, can anyone list evidence or provide reasoning either way, and if any problems/traps that might occur from thinking of it as 'self'?
A quick example:
type MyStruct struct {
Name string
}
Which method is more appropriate, or both?
func (m *MyStruct) MyMethod() error {
// do something useful
}
or
func (self *MyStruct) MyMethod() error {
// do something useful
}
I concur with Oliver Goodman's answer and admire the courage of his convictions in the face of such overwhelming odds.
Basically, the naysayers are saying that using "this" (my preference) as the receiver variable does NOT have precisely the same meaning as in other languages. So we should avoid it to preempt potential gotchas and keep confusion to a minimum.
But, of course, the same could be said about
->
and.
, not to mention many other C-like facets of Go (over which we have no control).However, using "this" in the way the OP implies makes it so much easier to understand context. And since we know we are programming in Go, we understand that it has different implications compared to other languages.
Using "this" also implies that our type ("class") methods are "conventional". If some weirdness is expected then you can always use another receiver moniker to emphasise this fact.
But let's not throw the baby out with the bathwater!
From the very start, I have found that hard core Gophers tend to be very rigid and unbending. But I must admit that this has served the language well in many many areas. And I take my hat off to them in that respect.
However, this same unyielding mindset has unleashed problems in other areas, The GOPATH craziness is the most obvious example.
Listening to the experts is no excuse for not thinking things through. Even the experts have blind spots and hang-ups whose magnitude is often in direct proportion to their speciality.
Short answer: Use the convention that suits you best!
In addition to what others said (especially
PeterSO
anddskinner
—in his comment to the Peter's answer), note several important things:You can call a method like a simple function
In Go, you can call any method function not as a method on a receiver but rather as a regular function—simply by qualifying its name with the name of the type it's defined to be a method on and explicitly passing it a receiver argument (obtaininig a simple function from a method is called using a method expression).
To demonstrate:
(Playground link.)
When run, this program prints:
As you can see,
self
loses its sacred meaning here because you've just called a method artifically constructing the context for it which has nothing to do with the much cited "calling an object's method is passing a message to that object" concept.To recap, in Go, a method is just a function semantically bound to a particular type which receives a single extra argument—its receiver—no matter how it's called. Contrary to many other mainstream languages, Go does not hide this fact under the carpet.
A receiver is not necessarily mutable inside a method defined on its type
As demonstrated in my example, I've defined a method,
Bar()
, on a non-pointer receiver, and if you'll try to assign a value to the receiver that will succeed but won't affect the caller because the receiver—as everything in Go—has been passed by value (so that integer has just been copied).To be able to mutate the receiver's value in the method, you'd have to define it on an appropriately-typed pointer, like
Again, you can see that using
self
meaning "me", "my internals" becomes moot here: in my example the method merely received a value which type it knows. You can see this is in contrast with many OO-languages in which an object is a black box usually passed around by reference. In Go, you can define a method on virtually anything (including other methods, which is used by thenet/http
standard package, by the way) which erodes that "methods are for objects" concept.Different sets of methods might be applicable to the same value at different times
In Go, methods are a convenient way to group functionality around particular types, and different sets of methods might be applicable to the same value in different points of the program flow. Combined with interfaces and duck-typing they provide, this concept really flourishes. The idea is that in Go, there's an idiom of defining "support" types which perform certain operation on values of some other type.
A good example of this is the standard package
sort
: for instance, it provides the typeIntSlice
which allows you to sort a slice of integers—a value of type[]int
. To do that you type-convert your slice tosort.IntSlice
and the value you get as a result has a whole set of methods for sorting your slice while the internal representation of your value has not changed— becausesort.IntSlice
is defined astype IntSlice []int
. In each method of thatIntSlice
type, it's hard to reconcile the meaning of their receiver value withself
—simply because the type solely exists to provide a set of methods for another type; in a philosophical sense, such utility types have no concept of "self" ;-)Conclusion
So I'd say, keep things simple in your head and do not try to "overload" the clear and simple approach taken by Go with semantics it does not explicitly state it provides.
One more note. My personal perception of Go's idioms as I learned them is that the paramount property of Go is its practicality (as opposed to idealism etc) so if you see some concept which "feels" unnatural try to work out why it's designed that way, and most often you'll discover why so the concept "clicks" in your brain and gets natural. (I must admit that to grok this particular problem with understanding methods in Go, a good working familiarity with
C
would be of much help.)The Go wiki recommends not using terms like
this
orself
and instead using abbreviations derived from the type name: https://github.com/golang/go/wiki/CodeReviewComments#receiver-namesLook at the source code for Go commands and Go standard packages for exemplars of good programming style. The name
self
is not used for Go method receivers.Go Source Code
The name
self
is a Python convention. Go is not Python.I can see no particularly compelling reason to avoid the
this
/self
convention. Other posts here merely cite community norms or describe aspects of method dispatch which have no bearing on naming conventions.These code review guidelines reject
this
orself
without giving any reason at all, unless you can read something into the implied claim that go places less emphasis on methods than other languages.One advantage of committing to a
this
orself
convention is that it helps to highlight violations of the Law of Demeter. Code such as this:appears on the face of it to be reaching into
w
's members inappropriately. In fact it is accessing members of its receiver, which is perfectly proper.