Reputation: 7136
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)
}
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.
Upvotes: 48
Views: 65681
Reputation: 27
Shortly, though we can use slice to modify the source data, but for slice itself, when as an argument for function, it just pass a copy into the function. so, your code like this
func test(i int) {
i = i + 1
}
var a int = 3
test(a)
Upvotes: -2
Reputation: 11551
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)
}
Upvotes: 9
Reputation: 2545
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)
}
Upvotes: 60