Struct 具有嵌套映射的golang结构

Struct 具有嵌套映射的golang结构,struct,go,maps,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 {

嗨,我是新来的,我想弄清楚地图是怎么工作的。 我已经制定了一个小测试程序,似乎无法使它工作。 我做错了什么

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

您的方法存在一些问题

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

  • 映射返回其值的副本。所以当你拉出“aa”并修改它时,你会得到一个“aa”的副本,改变它,然后扔掉它。你需要把它放回地图,或者使用指针

下面是上的一个工作示例(非指针版本)。
请注意贴图的构造,以及在修改值时重新指定回贴图

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

该代码存在两个问题:

  • 需要使用make函数初始化映射。目前为零

  • 来自映射的返回值是不可寻址的,这是因为如果映射正在增长,它需要重新定位,这将导致内存地址更改。因此,我们需要显式地将值从映射中提取到变量,更新它并将其重新赋值

  • 使用指针

  • 我已经更新了解决方案,以显示返回的更新it值,并将其赋值回指针


    将此添加为解决问题的不同方法:

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

    stats.category[“aa”]
    应该是事件片段的字符串映射,但您试图将其赋值为66。感谢您的解决方案,这正是我一直在寻找的。我花了一些时间才找到您发布的此答案,但现在有意义了
    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)
    }