Pointer and Slice Pointer - Receiver

I think it will be a little obvious as soon as he calls me, but now the next one is not a tap.

type Stack []interface{} func (stack *Stack) Push(x interface{}) { *stack = append(*stack, x) } 

I have a Stack type, which is a piece of empty interfaces. Given that it is empty, the Push method satisfies the interface. Given that a slice is a reference type, why can't the "stack receiver" be passed by value? Moreover, in the above example, the receiver is passed as a pointer, why is adding the built-in component necessary again to pass the pointer?

IE why doesn't this work, given that the slice is a reference pointer to the underlying array?

 func (stack Stack) Push(x interface{}) { stack = append(stack, x) } 
+5
source share
2 answers

See the Go blog article. He explains in detail what is happening and fully answers your question.

In the section Transfer slices in functions :

It is important to understand that although a slice contains a pointer, it is itself a value. Under covers is a structure value containing a pointer and a length. This is not a pointer to a structure.

As a result, you need a pointer receiver, or you need to return the slice as a value if you want to change it using append .

If you just want to change the contents of the fragment, you can simply pass the slice by value:

Despite the fact that the slice header is passed by value, the header includes a pointer to the elements of the array, so both the original slice header and a copy of the header passed to the function describe the same array. Therefore, when a function returns, modified elements can be visible through the original slice variable.

With append you change the slice title. AND

Thus, if we want to write a function that changes the title, we must return it as a result parameter

Or:

Another way to have the function to change the slice header is to pass a pointer to it.

You also have confusion about using pointers. See spec :

For operand x of type T, the operation address & x generates a pointer of type * T to x.

and

For operand x of type pointer * T, pointer-pointer * x denotes a variable of type T pointed to by x.

So your example *stack = append(*stack, x) does not mean that you are passing a pointer to append , quite the opposite - you are casting a pointer to pass the value that it points to.

+7
source

The problem you are facing is that append returns a link to a new slice. You cannot change the value of a function receiver unless it is a pointer.

What I would recommend rather makes a wrapper structure:

 type Stack struct{ data []interface{} size int } func (s *Stack) Push(i interface{}){ s.data = append(s.data,i) s.size++ } 
+2
source

All Articles