FuriousGeorge
FuriousGeorge

Reputation: 4681

Modify array of interface{} golang

This type assertion, def-referencing has been driving me crazy. So I have a nested structure of Key string / Value interface{} pairs. Stored in the Value is an []interface which I want to modify each of the values. Below is an example of creating an array of Bar and passing it into the ModifyAndPrint function which should modify the top level structure. The problem that I come accross is as written it doesn't actually modify the contents of z, and I can't do a q := z.([]interface{})[i].(Bar) or & thereof.

Is there a way to do this? If so, what combination did I miss?

package main

import "fmt"

type Bar struct {
   Name string
   Value int
}

func ModifyAndPrint(z interface{}){
    fmt.Printf("z before: %v\n", z)
    for i, _ := range(z.([]interface{})) {      
        q := z.([]interface{})[i]
        b := (q).(Bar)
        b.Value = 42
        fmt.Printf("Changed to: %v\n", b)
    }
    fmt.Printf("z after: %v\n", z)
}

func main() {       
    bars := make([]interface{}, 2)
    bars[0] = Bar{"a",1}
    bars[1] = Bar{"b",2}

    ModifyAndPrint(bars)    
}

https://play.golang.org/p/vh4QXS51tq

Upvotes: 3

Views: 3145

Answers (1)

Thundercat
Thundercat

Reputation: 121049

The program is modifying a copy of the value in the interface{}. One way to achieve your goal is to assign the modified value back to the slice:

for i, _ := range(z.([]interface{})) {      
    q := z.([]interface{})[i]
    b := (q).(Bar)
    b.Value = 42
    z.([]interface{})[i] = b
    fmt.Printf("Changed to: %v\n", b)
}

playground example

Upvotes: 7

Related Questions