嵌套映射golang的结构

时间:2016-01-24 04:16:48

标签: struct go maps

嗨,我是新来的,并试图找出地图的工作原理。 我做了一个小测试程序,似乎无法让它工作。 我做错了什么?

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

3 个答案:

答案 0 :(得分:7)

代码有几个问题:

  1. 需要使用make函数初始化Map。目前他们是零

  2. map中的返回值是不可寻址的,这是因为如果map正在增长,则需要重新定位,这将导致内存地址发生变化。因此,我们需要从map中明确地提取值到变量,更新它并将其分配回来。

  3. 使用指针

  4. 我已经更新了解决方案,以显示返回的更新值并将其分配回指针。

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

答案 1 :(得分:2)

将此问题添加为解决问题的另一种方法:

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

答案 2 :(得分:0)

您的方法存在一些问题。

  • 您没有初始化地图。您需要先创建它们。

  • 地图会返回其值的副本。所以,当你退出" aa"并修改它,你得到一个" aa"的副本,更改它,然后扔掉它。您需要将其放回地图中,或使用指针。

这是Play上的一个工作示例(非指针版本) 注意地图的构造,以及在修改值时重新分配回地图。

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 := &Stats{category: map[string]Events{}}
    stats.cnt = 33
    tmpCat, ok := stats.category["aa"]
    if !ok {
        tmpCat = Events{event: map[string]Event{}}
    }
    tmpCat.cnt = 66
    tmpEv := tmpCat.event["bb"]

    tmpEv.value = 99
    tmpCat.event["bb"] = tmpEv
    stats.category["aa"] = tmpCat

    fmt.Println(stats.cnt, stats.category["aa"].event["bb"].value)
}