烙印99
该地图类型:映射是一种类型的无序元素组,称为元素类型,由一组另一种类型的唯一键索引,称为键类型。映射类型必须具有特定的值类型和特定的键类型。你想要的不符合这个条件:你想要一个值有时是另一个映射(相同类型)的映射,有时它是一个bool.您的选择:1. 带包装值类型这里的想法是不仅仅使用简单的 ( bool) 值类型,而是使用一个包装器来保存您的两个潜在值:amap和简单值 ( bool):type Value struct { Children MapType V bool}type MapType map[int]*Valuevar m MapType这基本上是 user3591723 建议的,所以我不会进一步详细说明。2. 带着一棵树这是#1 的变体,但通过这种方式我们可以清楚地传达它是一棵树。实现层次结构的最简洁的方法是使用树,其中的节点可能如下所示:type KeyType inttype ValueType stringtype Node struct { Children map[KeyType]*Node Value ValueType}这样做的好处是您可以选择值类型(这是bool您的情况,但您可以将其更改为任何类型 - 我用于string演示)。为了轻松构建/管理您的树,我们可以在我们的Node类型中添加一些方法:func (n *Node) Add(key KeyType, v ValueType) { if n.Children == nil { n.Children = map[KeyType]*Node{} } n.Children[key] = &Node{Value: v}}func (n *Node) Get(keys ...KeyType) *Node { for _, key := range keys { n = n.Children[key] } return n}func (n *Node) Set(v ValueType, keys ...KeyType) { n = n.Get(keys...) n.Value = v}并使用它:1. 构建一棵树,2. 查询一些值,3. 更改一个值:root := &Node{Value: "root"}root.Add(0, "first")root.Get(0).Add(9, "second")root.Get(0, 9).Add(3, "third")root.Get(0).Add(4, "fourth")fmt.Println(root)fmt.Println(root.Get(0, 9, 3))fmt.Println(root.Get(0, 4))root.Set("fourthMod", 0, 4)fmt.Println(root.Get(0, 4))输出(在Go Playground上试试):&{map[0:0x104382f0] root}&{map[] third}&{map[] fourth}&{map[] fourthMod}3. 带有递归类型定义这可能令人惊讶,但可以map使用递归定义在 Go 中定义具有无限或动态“深度”的类型:type X map[int]X这就是它所说的:它是一个map带有int键和与地图本身相同类型的值。这种递归类型的最大缺点是它不能在值类型中存储任何“有用”的数据。它只能存储是否存在与类似bool信息(booltype:true或false)相同的值的“事实” ,这在极少数情况下可能就足够了,但在大多数情况下就不够了。让我们看一个构建“树”的例子:var x Xx = map[int]X{}x[0] = map[int]X{}x[0][9] = map[int]X{}x[0][9][3] = map[int]X{}x[0][4] = map[int]X{}fmt.Println(x)输出:map[0:map[9:map[3:map[]] 4:map[]]]如果我们想测试是否存在基于一系列键的“值”,我们有 2 个选项:使用特殊v, ok := m[i]索引(它报告指定键的值是否存在),或者测试该值是否不存在nil,例如m[i] != nil。让我们看一些测试上面构建的地图的例子:var ok bool_, ok = x[0][9][3]fmt.Println("x[0][9][3] exists:", ok, "; alternative way:", x[0][9][3] != nil)_, ok = x[0][9][4]fmt.Println("x[0][9][4] exists:", ok, "; alternative way:", x[0][9][4] != nil)_, ok = x[0][4]fmt.Println("x[0][4] exists:", ok, "; alternative way:", x[0][4] != nil)_, ok = x[0][4][9][9][9]fmt.Println("x[0][4][9][9][9] exists:", ok, "; alternative way:", x[0][4][9][9][9] != nil)输出:x[0][9][3] exists: true ; alternative way: truex[0][9][4] exists: false ; alternative way: falsex[0][4] exists: true ; alternative way: truex[0][4][9][9][9] exists: false ; alternative way: false在Go Playground上试试这些。注意:即使x[0][4]是最后一个“叶子”,进一步索引x[0][4][9][9][9]也不会引起恐慌,因为nil可以索引映射并产生值类型的零值(nil如果值类型是映射类型)。