Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defining golang struct function using pointer or not

Tags:

go

Can someone explain to me why appending to an array works when you do this:

func (s *Sample) Append(name string) {     d := &Stuff{         name: name,     }     s.data = append(s.data, d) } 

Full code here

But not when you do this:

func (s Sample) Append(name string) {     d := &Stuff{         name: name,     }     s.data = append(s.data, d) } 

Is there any reason at all why you would want to use the second example.

like image 443
Jay Avatar asked Aug 19 '14 11:08

Jay


People also ask

Should I use a pointer instead of a copy of my struct?

Illustration created for “A Journey With Go”, made from the original Go Gopher, created by Renee French. For many Go developers, the systematic use of pointers to share structs instead of the copy itself seems the best option in terms of performance.

Is struct a pointer in Golang?

Access struct using pointer in Golang In the above example, we have used the struct type pointer to access struct members: ptr.name - gives the value of the name member.

Does struct need a pointer?

They are not implemented as pointers. when you use the subscript operator [] on a pointer, it is interpreted as requesting the element at that position. so the compiler is simply able to determine the offset because the size of the struct is known/constant.

Should I return a pointer or struct in Golang?

Structs must be pretty large that returning a pointer makes your program faster. Just don't bother, code, profile, fix if useful. There is only one way to return a value or a pointer, and that is to return a value, or a pointer.


2 Answers

As mentioned in the FAQ

Should I define methods on values or pointers?

func (s *MyStruct) pointerMethod() { } // method on pointer func (s MyStruct)  valueMethod()   { } // method on value 

First, and most important, does the method need to modify the receiver? If it does, the receiver must be a pointer. (Slices and maps act as references, so their story is a little more subtle, but for instance to change the length of a slice in a method the receiver must still be a pointer.)

In the examples above, if pointerMethod modifies the fields of s, the caller will see those changes, but valueMethod is called with a copy of the caller's argument (that's the definition of passing a value), so changes it makes will be invisible to the caller.

In your case, func (s Sample) Append(name string) modifies a copy.

laher reminds us in the comments that using a value instead of pointer also means getting a copy, and respecting the immutable nature of an object::

You'd want to use the non-pointer valueMethod when (for nstance) you're returning a [value derived from an] 'immutable' private property.

See "Why are receivers pass by value in Go?":

Can be useful if for instance you have a small immutable object. The caller can know for certain that this method doesn't modify it's receiver.
They can't know this if the receiver is a pointer without reading the code first.

like image 166
VonC Avatar answered Oct 01 '22 21:10

VonC


Go slices are a tricky beast. Internally, a variable of slice type (like []int) looks like this:

struct {     data *int // pointer to the data area     len  int     cap  int } 

When you pass a slice to a function, this structure is passed by value, while the underlying data area (i.e. what data points to) is not copied. The builtin append() function modifies the data area (or generates a new one) and returns a new slice with updated len, data, and cap values. If you want to overwrite anything that is not part of the underlying data area, you need to pass a pointer to the slice or return a modified slice.

like image 38
fuz Avatar answered Oct 01 '22 22:10

fuz