Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

structure with nested maps golang

Tags:

struct

go

maps

Hi I'm new to go and was trying to figure out how maps work. I have made up a little test program and can't seem to get it to work. What I'm doing wrong?

package main

import (
    "fmt"
)

type Stats struct {
    cnt      int
    category map[string]Events
}

type Events struct {
    cnt   int
    event map[string]Event
}

type Event struct {
    value int64
}

func main() {

    stats := new(Stats)
    stats.cnt = 33
    stats.category["aa"].cnt = 66
    stats.category["aa"].event["bb"].value = 99

    fmt.Println(stats.cnt, stats.category["aa"].event["bb"].value)
}
like image 831
Daniel Huckson Avatar asked Jan 24 '16 04:01

Daniel Huckson


People also ask

How do I create a nested map in Golang?

Golang Create Nested Map We can define a nested map the same way we declare a normal map. We start by setting the data type of the key (top-level map) and the type of the value. Since this is a nested map, the value of the top-level map is a map. The previous code creates a simple restaurant menu using nested maps.

How do I iterate over a map in Golang?

You can iterate through a map in Golang using the for... range statement where it fetches the index and its corresponding value. In the code above, we defined a map storing the details of a bookstore with type string as its key and type int as its value. We then looped through its keys and values using the for..

What is a nested map?

Nested Maps are those in which values in key:value pairs of the outer map are also maps. In other words maps inside a map, hence nested maps.

What is type struct go?

In Go programming, a structure or struct is a user-defined type to store a collection of different fields into a single field. For example, suppose you have a player and want to store his name and age. You can create two variables, name, and age, to store the values.


2 Answers

There are couple of issues with the code:

  1. Map needs to be initialized using make function. Currently they are nil

  2. Return value from map is non-addressable, this because if map is growing it needs to relocated which will cause memory address to change. Hence we need to extract value explicitly from map to a variable, update it and assigning it back.

  3. Use pointer

I have updated the solution to show both updated it value returned and assigning it back and pointer.

http://play.golang.org/p/lv50AONXyU

package main

import (
    "fmt"
)

type Stats struct {
    cnt      int
    category map[string]Events
}

type Events struct {
    cnt   int
    event map[string]*Event
}

type Event struct {
    value int64
}

func main() {

    stats := new(Stats)
    stats.cnt = 33
    stats.category = make(map[string]Events)
    e, f := stats.category["aa"]
    if !f {
        e = Events{}
    }
    e.cnt = 66

    e.event = make(map[string]*Event)
    stats.category["aa"] = e
    stats.category["aa"].event["bb"] = &Event{}
    stats.category["aa"].event["bb"].value = 99

    fmt.Println(stats)
    fmt.Println(stats.cnt, stats.category["aa"].event["bb"].value)
}
like image 94
Prashant Thakkar Avatar answered Oct 12 '22 12:10

Prashant Thakkar


Adding this as a different approach to the problem:

type Stats struct {
    cnt        int
    categories map[string]*Events
}

func (s *Stats) Category(n string) (e *Events) {
    if s.categories == nil {
        s.categories = map[string]*Events{}
    }
    if e = s.categories[n]; e == nil {
        e = &Events{}
        s.categories[n] = e
    }
    return
}

type Events struct {
    cnt    int
    events map[string]*Event
}

func (e *Events) Event(n string) (ev *Event) {
    if e.events == nil {
        e.events = map[string]*Event{}
    }
    if ev = e.events[n]; ev == nil {
        ev = &Event{}
        e.events[n] = ev
    }
    return
}

type Event struct {
    value int64
}

func main() {
    var stats Stats
    stats.cnt = 33
    stats.Category("aa").cnt = 66
    stats.Category("aa").Event("bb").value = 99

    fmt.Println(stats)
    fmt.Println(stats.cnt, stats.Category("aa").Event("bb").value)
}

playground

like image 26
OneOfOne Avatar answered Oct 12 '22 14:10

OneOfOne