使用Golang创建具有嵌套映射的结构体。

huangapple go评论87阅读模式
英文:

structure with nested maps golang

问题

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)

}

英文:

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

答案1

得分: 22

代码存在几个问题:

  1. Map需要使用make函数进行初始化。目前它们是nil。

  2. 从map返回的值是不可寻址的,这是因为如果map正在增长,它需要重新定位,这将导致内存地址发生变化。因此,我们需要将值显式地从map中提取到一个变量中,对其进行更新,并将其重新赋值。

  3. 使用指针。

我已经更新了解决方案,以显示更新后的值和重新赋值以及指针。

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

你可以在这里查看更新后的代码:http://play.golang.org/p/lv50AONXyU

英文:

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

答案2

得分: 4

将这段代码翻译成中文如下:

// 将这段代码作为解决问题的另一种方法添加进来:

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

英文:

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

<kbd>playground</kbd>

答案3

得分: 1

你的方法存在一些问题。

  • 你没有初始化你的映射。你需要先创建它们。

  • 映射返回的是值的副本。所以当你取出"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)
}
英文:

There are a few issues with your approach.

  • You aren't initializing you maps. You need to create them first.

  • Maps return copies of their values. So when you pull out "aa" and modify it, you are getting a copy of "aa", changing it, then throwing it away. You need to put it back in the map, or use pointers.

Here's a working example (non-pointer version) on Play.
Notice the construction of the maps, and the re-assignment back to the map when modifying a value.

package main

import (
	&quot;fmt&quot;
)

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

	tmpEv.value = 99
	tmpCat.event[&quot;bb&quot;] = tmpEv
	stats.category[&quot;aa&quot;] = tmpCat

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

huangapple
  • 本文由 发表于 2016年1月24日 12:16:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/34972157.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定