15

On the closest thing Golang has to a style guide found here, under Receiver Names this is written:

The name of a method's receiver should be a reflection of its identity; often a one or two letter abbreviation of its type suffices (such as "c" or "cl" for "Client"). Don't use generic names such as "me", "this" or "self", identifiers typical of object-oriented languages that place more emphasis on methods as opposed to functions. The name need not be as descriptive as a that of a method argument, as its role is obvious and serves no documentary purpose.

I personally have always just used "this" as the identifier because "this" is the focus of what I am working on when I write and edit the function. It sounds right, and (to me at least) it makes sense.

If the name need not be descriptive, it's role is obvious, and it serves no documentary purpose, why would the use of "this" be frowned upon?

Alexander
  • 3,562
  • 1
  • 19
  • 24
Adam
  • 1,367
  • 3
  • 12
  • 15

5 Answers5

12

We'd have to ask the author of that style guide to know for sure, but I think the main reason I kind of agree with him is that the connection between struct and method is much looser in Go than other languages.

In essence, when you write a method like this:

func (m *MultiShape) area() float64 {
  ...
}

That's almost exactly the same thing as writing a function like this:

func area(m *MultiShape) float64 {
  ...
}

The only difference is a slight syntax change in how we call the function/method.

In other languages the this/self/whatever variable typically has some special properties such as being magically provided by the language, or having special access to private methods (remember Go doesn't have private fields/methods). Though the "receiver" is still being "magically provided" to some extent, it's so similar to a regular function argument it arguably doesn't count.

Plus, in "traditional" OOP languages a struct/class' methods all come with the struct/class definition, such that no more can be added from outside. In Go, as far as I know anyone can add more methods to anything (within the scope of their own code, of course).

I haven't written enough Go to make my own style guide, but personally I'd probably use this in methods defined in the same file as the struct they receive, and some more descriptive receiver name on methods that I attach to structs from other files.

Ixrec
  • 27,621
  • 15
  • 80
  • 87
  • That's a good explanation, I suppose I'm used to C# and other OOP languages so I'm reverting to conventions I know. – Adam Jun 11 '15 at 08:23
  • 1
    @Adam I would avoid `this` if for no other reason than to remind myself that I'm not in a traditional OOP language. – Michael Hampton Jul 09 '16 at 00:03
  • 7
    There is no real difference between "this" and "receiver" (and please stop abusing word "magic" - every feature of a high level programming language can be called "magic", this doesn't make it anything negative, your attempt to pick on "this" for being "magic" makes no sense). – mvmn Jul 05 '17 at 14:04
  • @mvmm Extreme care and diligence needs to be taken though in explaining magic to someone who is not familiar with it. It is not by chance witches used to be burned by the stake. – Zyl Feb 19 '21 at 13:23
  • I guess the only "magic" that really can make a difference is that `this` in garden-variety OOP languages can be polymorphic, while in Go it never is? Personally, I never understood the big deal people make about method/function distinction. Perhaps this is because of my C++ background, which means that for me every method is just a function, except when `virtual` - than it's still just a function, but with funny call semantics. Though it's true that `this` is polymorphic in C++ too, also in non-virtual methods - so maybe I just wasn't appreciating the difference enough? – Frax Jan 28 '22 at 01:12
11

I am not convinced by this style guide and I don't think anything is better than this, me or self. Because this, me or self makes it super clear that the variable is an instance of the context struct. I'm not saying a lower cased struct name variable is a bad idea, I just like the way that this makes it super clear.

Qian Chen
  • 226
  • 2
  • 5
  • without an explanation, this answer may become useless in case if someone else posts an opposite opinion. For example, if someone posts a claim like _"I am convinced by this style guide and I think it is better than `this`, `me` or `self`"_, how would this answer help reader to pick of two opposing opinions? Consider [edit]ing it into a better shape, to meet [answer] guidelines – gnat Dec 26 '16 at 05:05
  • I think I have clearly explained what I wanted to say. – Qian Chen Jan 10 '18 at 07:55
  • 1
    I agree. I think there are too many brains poisoned by the javascript context. If you put that aside. That this refers to the current context is much simpler. And easier if you rename structs later on, or copy paste part of an implementation. Gong for short cryptic names line h. l. etc does not make it any easier than this. – Sentient Jun 08 '18 at 15:37
4

I have realized this only while reading the answers here:

There is a real and significant difference between receiver in Go and this/self in most (all?) OOP languages: receiver is never polymorphic.

When you have a method in C++ or Java and call this.someMethod(foo) then at this call site, without looking up the signature, you can't tell whether this method may be overriden or not. In Go, you know it isn't - you don't even have a real inheritance in Go, so there are no overrides. This can be both useful and limiting. On one hand, it prevents some unlucky overrides from breaking the logic for the base class, which may happen with virtual inheritance. On the other hand, it prevents doing things traditional, OOP way.

I actually wrote a simple test to make sure I didn't imagine something (it's quite late and I'm not feeling sharpest right now :P):

// You can edit this code!
// Click here and start typing.
package main

import "fmt"

type BaseStruct struct {
    baseVal int
}

func (t *BaseStruct) callNotPolymorphicOnSelf() string {
    // Always calls notPolymorphic defined for *Test, no matter what this struct is composited into.
    return t.notPolymorphic()
}
func (t *BaseStruct) notPolymorphic() string {
    return "<executing (*BaseStruct) function>"
}

type ComposedStruct struct {
    BaseStruct
    addedVal int
}

func (t *ComposedStruct) notPolymorphic() string {
    return "<executing (*ComposedStruct) function>"
}

type interfaceThatChangesNothing interface {
    callNotPolymorphicOnSelf() string
}

func fromIface(it interfaceThatChangesNothing) string {
    return it.callNotPolymorphicOnSelf()
}

func main() {
    var composedStruct ComposedStruct
    fmt.Printf("Calling composedStruct.callNotPolymorphicOnSelf(): %v\n", composedStruct.callNotPolymorphicOnSelf())
    fmt.Printf("Calling callNotPolymorphicOnSelf() through interface: %v\n", fromIface(&composedStruct))
    fmt.Printf("Calling notPolymorphic directly on composedStruct: %v\n", composedStruct.notPolymorphic())
}

Result:

Calling composedStruct.callNotPolymorphicOnSelf(): <executing (*BaseStruct) function>
Calling callNotPolymorphicOnSelf() through interface: <executing (*BaseStruct) function>
Calling notPolymorphic directly on composedStruct: <executing (*ComposedStruct) function>

See live in Go Playground

Frax
  • 1,844
  • 12
  • 16
  • 1
    This is a good answer, as it highlights the advantage of using Go's conventions. `this` and `self` have meaning other than Go's definition of "receiver", and what it can and can't do. So changing the convention has the potential to push you to think :) – dror Apr 15 '22 at 22:45
0

This is from a perspective of JavaScript where this has actual keyword meaning to the compiler, but from my understanding, if they're okay with two-letter abbreviations for the object type, it should be easy enough to use that instead. The reason for the difference is that in a decently-large block of progressively deeper asynchronous code, it could be very easy to misinterpret what "this", or the receiver, is in a deeper context; and it's possible it won't be the same object.

In JavaScript for instance, a control module might start up a dialog and declare an onLoad function inline for it. But at that point, it could be very easy for another coder to misinterpret this inside onLoad to refer to the control module, not the dialog; or vice versa. This could be avoided if the control were referred to as ctrl and the dialog as dg.

Katana314
  • 862
  • 1
  • 5
  • 18
  • 4
    I'm not the downvoter, but most of the confusing behaviors of `this` in Javascript simply do not apply to Go, so I'm guessing that's why. – Ixrec Jun 10 '15 at 16:21
  • @Ixrec Hm...okay. I was kind of trying to extend it to situations where you could choose `this`'s name; for instance, often JS coders will write `var self = this` to keep the same reference around; but according to Go's design guide, that could then have the same confusion issues, and theoretically should use a more descriptive reference. – Katana314 Jun 10 '15 at 17:12
  • With arrow functions this issue is fortunately mostly extinct in JS too, though you still can do any weird nesting, nested classes with methods with nested classes and so on. However, in Go you don't have these all weird kinds of nesting, so shadowing issues don't apply to `this`. – Frax Jan 28 '22 at 01:13
0

I'm firmly in the camp that this of self should not be used in Golang. It confuses other engineers on the behavior of the language if they are coming from something like PHP, Java, Python or JS. Here are some pretty good examples of why it could and probably will cause confusion: https://blog.heroku.com/neither-self-nor-this-receivers-in-go

There are no classes in Golang and it's not an OOP language so I personally would avoid it.

Shoe
  • 1