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.
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.
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.
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.
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.
As mentioned in the FAQ
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With