0
votes

Im trying to build a []map[string]interface{} using a loop like so:

package main

import (
    "encoding/json"
    "fmt"
)

type People []struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

func main() {
    resp := `[{"name":"Test","age":15}, {"name":"Test2","age":25}]`
    data := &People{}
    _ = json.Unmarshal([]byte(resp), data)
    m := make([]map[string]interface{}, len(*data))
    for k, v := range *data {
        m[k]["Name"] = v.Name
        m[k]["Age"] = v.Age
    }
    fmt.Println(m)
    fmt.Printf("%T", m)
}

But Im always getting this error:

panic: assignment to entry in nil map

goroutine 1 [running]: main.main() /tmp/sandbox300360207/prog.go:19 +0x17a

I cant use m := make(People, len(*data)) and m[k].Name = v.Name because I need the type to be []map[string]interface{} and not main.People

I also tried this:

func main() {
    resp := `[{"name":"Test","age":15}, {"name":"Test2","age":25}]`
    data := &People{}
    _ = json.Unmarshal([]byte(resp), data)
    m := make([]map[string]interface{}, len(*data))
    for k, v := range *data {
        m[k] = map[string]interface{"Name": v.Name, "Age": v.Age}
    }
    fmt.Println(m)
    fmt.Printf("%T", m)
}

But got this error:

./prog.go:19:31: syntax error: unexpected literal "Name", expecting method or interface name

1

1 Answers

2
votes

Your make() only creates a slice of maps, but its elements are all nils. You can't "insert" pairs into a nil map, you also have to create maps inside the loop:

m := make([]map[string]interface{}, len(*data))
for k, v := range *data {
    m[k] = make(map[string]interface{})
    m[k]["Name"] = v.Name
    m[k]["Age"] = v.Age
}

Output will be (try it on the Go Playground):

[map[Age:15 Name:Test] map[Age:25 Name:Test2]]
[]map[string]interface {}

Alternatively you may use a composite literal to create the map:

m[k] = map[string]interface{}{}

Your second attempt falls short because the syntax is invalid. The type is map[string]interface{}, so a composite literal to create a value of this type has to have an additional braces pair: map[string]interface{}{}. Using a single composite literal, this is how it would look like:

for k, v := range *data {
    m[k] = map[string]interface{}{
        "Name": v.Name,
        "Age":  v.Age,
    }
}

Output is the same. Try this one on the Go Playground.