go - 理解 `interface{}` 在 Go 中的用法的问题

标签 go

我正在尝试将算法从 Python 移植到 Go。它的中心部分是一棵使用字典构建的树,它应该保持这种状态,因为每个节点都可以有任意数量的子节点。所有的叶子都在同一层,所以最低层的字典包含其他字典,而最低层的字典包含 float 。像这样:

tree = {}
insert(tree, ['a', 'b'], 1.0)
print tree['a']['b']

因此,在尝试将代码移植到 Go 的同时学习这门语言,这就是我开始测试基本思想的方法:

func main() {
    tree := make(map[string]interface{})
    tree["a"] = make(map[string]float32)
    tree["a"].(map[string]float32)["b"] = 1.0
    fmt.Println(tree["a"].(map[string]float32)["b"])
}

这按预期工作,因此下一步是将其变成一个例程,该例程将采用“树”、路径和值。我选择了递归方法并想出了这个:

func insert(tree map[string]interface{}, path []string, value float32) {
    node := path[0]
    l := len(path)
    switch {
    case l > 1:
        if _, ok := tree[node]; !ok {
            if l > 2 {
                tree[node] = make(map[string]interface{})
            } else {
                tree[node] = make(map[string]float32)
            }
        }
        insert(tree[node], path[1:], value) //recursion
    case l == 1:
        leaf := tree
        leaf[node] = value
    }
}

这就是我想象中例程的结构,但我无法让标有“递归”的行起作用。如果我尝试对 tree[node] 执行类型断言,则会出现编译器错误或运行时错误。执行此操作的正确方法是什么?

最佳答案

对于这样的通用数据结构,Go 可能不是理想的解决方案。类型断言使之成为可能,但在其中操作数据需要您在 Python 和其他脚本语言中习惯的更多工作。

关于您的具体问题:您在 insert() 调用中缺少类型断言。 tree[node] 的值此时是 interface{} 类型。该函数需要类型 map[string]interface{}。类型断言将解决这个问题。

这是一个工作示例:

package main

import "fmt"

type Tree map[string]interface{}

func main() {
    t := make(Tree)
    insert(t, []string{"a", "b"}, 1.0)

    v := t["a"].(Tree)["b"]
    fmt.Printf("%T %v\n", v, v)

    // This prints: float32 1
}

func insert(tree Tree, path []string, value float32) {
    node := path[0]
    len := len(path)

    switch {
    case len == 1:
        tree[node] = value

    case len > 1:
        if _, ok := tree[node]; !ok {
            tree[node] = make(Tree)
        }

        insert(tree[node].(Tree), path[1:], value) //recursion
    }
}

请注意,我为 map 创建了一个新类型。这使得代码更容易理解。我还对树节点和树叶使用了相同的“map[string]interface{}”。如果你想从结果树中得到一个 float ,需要另一个类型断言:

leaf := t["a"].(Tree)["b"]  // leaf is of type 'interface{}`.
val := leaf.(float32)

关于go - 理解 `interface{}` 在 Go 中的用法的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10899571/

相关文章:

goroutine 等待 channel 的响应并继续

unit-testing - 如何验证在单独的 go 例程中调用了一个方法

go - 为什么我在以下带有延迟的 golang 代码示例中得到 0 和 1

Golang Web应用程序安全: should you check if input is valid utf-8?

go - Go 上的十进制到大写十六进制字符串

go - 从文件中的 yaml 对象获取值

postgresql - 从存储过程中检索结果的惯用方法是什么?

go - 运行测试时“无法创建临时输出文件”

go - big.Rat 中的数据竞赛

go - 尝试使用gob.Decoder()解码Blob时出现错误(gob:未知类型ID或损坏的数据)