Go Pointers - append values to slice via pointer

37,535

Solution 1

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

Solution 2

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)
}
Share:
37,535
Prateek
Author by

Prateek

Java is an ocean and I want to explore all of its corners. Also interested in DIY & Productivity hacks that help in reducing the work/time taken. Learning my way through new technologies - Go, Node.js

Updated on July 09, 2022

Comments

  • Prateek
    Prateek 4 months

    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.