0

We're trying to write Go in the most possibile idiomatic way, but sometimes we struggle to find which is the best way.

For example in our service we're creating/converting a struct from another one:

type Foo struct {
    ID int
}

type Bar struct {
    ID int
}

Is it better to write something like:

func convertAtoB(a A) *B {
    return &B{a.ID}
}

or something like this?

func (a* A) convertToB() *B {
    return &B{a.ID}
}

Of course in practice there's no difference, I just would like to understand when to choose one way over the other one.


EDIT:

I've found an interesting article about this:
https://grisha.org/blog/2016/09/22/golang-receiver-vs-function/

4

There are two reasons to use functions with receivers:

  1. You will invoke the method through an interface type.
  2. You really like the method-call syntax.

In all other cases (that I'm aware of), normal functions without receiver arguments are preferable.

2
  • +1 for the interface, I didn't thought about that.
    – Enrichman
    Aug 10 '17 at 16:42
  • 5
    It (making the function a method) helps logically group the function. There's no strict reason why you should do it, other than it's convention. Do note that a method can be called like a function; that is, (T).foo is equivalent to foo(T). It's just syntactic sugar. Aug 11 '17 at 15:17
1

I recently stumbled onto a receiver related thing that somehow very quickly someone on the Github found me the answer I was looking for. Just to explain, what I wanted was to be able to embed a first class function that had a receiver - in this case that happened to be exactly the struct type where I wanted to put it. I found a workaround using type Name func syntax, and then creating a private function that was wrapped in a type bound receiver from an interface, but this let me do it differently - the workaround was cumbersome and boilerplatey.

Here is the Github issue:

https://github.com/golang/go/issues/24996#issuecomment-383424588

I have not been able to find any further documentation about this, but essentially the main points are that you can create an interface{} field in a struct type, and then assign a function bound to an interface method collection, like this:

type Name Struct {
  ...
  funcSlot interface{}
  ...
}

func (n *Name) FuncName() error {
  return nil
}

func NewName() (n *Name) {
  ...
  n.funcSlot = (*Name).FuncName
  ...
}

type NAME interface {
  ...
  FuncName() error
  ...
}

This passes go vet, at least, I haven't yet confirmed that this has the effect of passing the pointer to the struct so that the function can operate on what is effectively a class.

0

You can refer to this link. It's one of the best answer I have come across on this subject.

The author concludes,

Bottom line is that it only makes sense to use a receiver if this function is part of an interface implementation, OR if you never ever need to augment (stub) that function for testing or some other reason. As a practical matter, it seems like (contrary to how it’s done in the OO world) it is better to always start out with quack(d) rather than d.quack().

New contributor
Shardul is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.