Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Go Pointers - append values to slice via pointer

Tags:

slice

pointers

go

I have a struct ProductData and its instance p which has a slice attribute :

type ProductInfo struct {     TopAttributes []map[string]interface{} } 

I want to set TopAttributes as follows

func (p *ProductInfo) setAttributeData() {     key := "key"     value := "value"     setAttribute(p.TopAttributes, key, value) }  func setAttribute(p []map[string]interface{}, key string, value interface{}) {     val := map[string]interface{}{         key: value,     }     p = append(p, val) } 

But this does not seem to work.

However, there is another way which works fine when I define a method as:

   func (p *ProductInfo) setAttributeData() {     key := "key"     value := "value"     p.setAttribute(key, value) }  func (p *ProductInfo) setAttribute(key string, value interface{}) {     val := map[string]interface{}{         key: value,     }     p.TopAttributes = append(p.TopAttributes, val) } 

I want to find out why it is not working. There were no errors in my code, but the data coming was empty. I am trying to do this to make it a generic function as I have another BottomAttributes which has to be set the same way.

like image 677
Prateek Avatar asked Jun 15 '16 12:06

Prateek


People also ask

Is a slice in Golang a pointer?

Go Pointers Slices are Pointers to Array Segments Slices are pointers to arrays, with the length of the segment, and its capacity. They behave as pointers, and assigning their value to another slice, will assign the memory address.

How do I add a slice in Golang?

To add an element to a slice , you can use Golang's built-in append method. append adds elements from the end of the slice. The first parameter to the append method is a slice of type T . Any additional parameters are taken as the values to add to the given slice .

How do you add a pointer to an array?

p = arr; // Points to the whole array arr. p: is pointer to 0th element of the array arr, while ptr is a pointer that points to the whole array arr. The base type of p is int while base type of ptr is 'an array of 5 integers'.

How do I dereference a pointer in Golang?

The * and & operators In Go a pointer is represented using the * (asterisk) character followed by the type of the stored value. In the zero function xPtr is a pointer to an int . * is also used to “dereference” pointer variables. Dereferencing a pointer gives us access to the value the pointer points to.


2 Answers

append returns a reference to the appended-to slice. This is because it could point to a new location in memory if it needed to be resized.

In your first example, you are updating the variable passed to your setAttribute function, but that's it. The only reference is lost when that function exits.

It works in the second example because that variable lives in your struct, and is thus updated.

You can fix the first version by using a pointer:

func (p *ProductInfo) setAttributeData() {     key := "key"     value := "value"     setAttribute(&p.TopAttributes, key, value) }  func setAttribute(p *[]map[string]interface{}, key string, value interface{}) {     val := map[string]interface{}{         key: value,     }     *p = append(*p, val) } 
like image 100
Kevin M Granger Avatar answered Nov 08 '22 07:11

Kevin M Granger


You are trying to append a map value which is used as a function parameter, so it has a local scope, accessible only within the function. Because this is referenced by value and not by pointer address, it's access is restricted only to it's local scope.

Map types are reference types, like pointers or slices, and so the value of parameter p is nil; it doesn't point to an initialized map.

To point it to a map you have to access trough it's pointer:

func (p *ProductInfo) setAttributeData() {     key := "key"     value := "value"     setAttribute(p.TopAttributes, key, value) }  func setAttribute(p *[]map[string]interface{}, key string, value interface{}) {     val := map[string]interface{}{         key: value,     }     *p = append(*p, val) } 
like image 39
Endre Simo Avatar answered Nov 08 '22 08:11

Endre Simo