Go Pointers - append values to slice via pointer

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.

1 Like

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)
}

Refer: go-pointers-append-values-to-slice-via-pointer