Constructor returns copy but methods are pointer receivers, good or bad?

Hi,

In example below my constructor returns a copy of User type. However, all the methods are using pointer receivers. So:

  1. I don’t understand why SetName works, because the constructor is not returning *User. I am not saying it shouldn’t but I want to understand.
  2. If the methods are using pointer receivers, would it not be the right way if the constructor returned *User instead?

Thank you

package main

import "fmt"

func main() {
	usr := NewUser(1)
	usr.SetName("user_one")
	fmt.Println("Hello,", usr.GetName())
}

type User struct {
	id   int
	name string
}

func NewUser(id int) User {
	var usr User
	usr.id = id
	return usr
}

func (u *User) SetName(name string) {
	u.name = name
}

func (u *User) GetName() string {
	return u.name
}

Hi @gofrmqueaskbostnanal,

Think about it this way: the methods are always attached to their copy of the User struct. When the constructor creates the struct and returns a copy, the methods travel along with that copy.

The pointer receiver always represents the copy on which the methods are called.

The difference betewen pointer receiver and normal receiver is that a method can modify its type through a pointer receiver.

Hi @gofrmqueaskbostnanal as an extra note to @christophberger , New methods in Go return pointers all the time by convention, like u := new(User) or u := NewUser(1). You may not need Getters/Setters depending on your structure, pointer receiver functions don’t work on copies it is fast and directly uses the pointer to set the properties, however normal receiver function work on the copies of your struct which doesn’t let you set properties and it is not the fastest option (most of the time but depends on your struct size and CPU cache).

If you are between using a pointer struct or a normal struct, pls consider this article, everytime we use pointers or New methods, memory escapes to the heap instead of staying in the stack and being cached in CPU. In Go, it is not so common to define setters/getters unless the interface enforces you to do so.

Be wise, if your all methods are using pointer receiver methods, keep using them for all, if your all methods are using normal receiver methods, keep using them for all.

My advice in this example would be just using and avoiding getters/setters overhead on your struct. If you really need a constructor(in most small struct cases people actually don’t need it), just return a pointer.

type User struct {
	ID   int
	Name string
}

Reference: Go: Should I Use a Pointer instead of a Copy of my Struct? | by Vincent Blanchon | A Journey With Go | Medium

1 Like

@christophberger your answer is somehow attempts to address the questions but I don’t think it explicitly answers the questions. Feels like general level info.

@MrWormHole your attempt has all the irrelevant, random and derailed stuff. Nothing there is relevant to questions. Also some of your remarks/advice are just not true and not fact based.

Towards the bottom of the Method values section of the language specification, it says:

As with selectors, a reference to a non-interface method with a value receiver using a pointer will automatically dereference that pointer: pt.Mv is equivalent to (*pt).Mv.

As with method calls, a reference to a non-interface method with a pointer receiver using an addressable value will automatically take the address of that value: t.Mp is equivalent to (&t).Mp.

So in your code:

The compiler implicitly transforms this into:

(&usr).SetName("user_one")
fmt.Println("Hello,", (&usr).GetName())

@gofrmqueaskbostnanal Thank you for your honest feedback. Please keep in mind that people in this forum spend their free time and their energy to help other people. We are all volunteers here. No one is obliged to serve anybody. If the answers you get are not the answers you expect, feel free to refine your question so that people can better understand what you are asking for.

perhaps @skillian 's answer is more in line with what you are seeking. I also want to clarify something I cleared up today. In Go, the pointer usage is highly semantic meaning that every returned *struct or struct from the function may go or not go to the heap depending on heap escape analysis.

so pointer method receivers or normal method receivers are highly dependent on if you are mutating data on your end, if not you probably don’t need it and can use normal method receivers

there is no constructor in Go, it is just a function that returns the struct, the pointer struct or the interface, therefore getter/setter situation is rare. It is entirely up to you what you return from your NewS(). If you are using like this, assuming referencing the address on every method call could be little in your case even though it is implicit (&user).SetName every time.

That makes sense and clears all the questions. Straight to point answer. Thank you.

Seriously, no need for a lecture please. What beats the purpose of forums is that people writing bunch of words for the sake of answering a question. So for that reason, yes, no one should feel obliged to cause unnecessary noise in forums. Also, as you can see, someone is able understand the question very clearly and come up with a real answer so again, so I guess you can that there is nothing to be edited as far as the question goes. Again I thank you for the reasonable attempt.

I am normally not like this (I don’t like my tone here at all as it is just unacceptable by myself), time wasting answers push the button if you get what I mean.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.