douyue8685 2012-06-05 14:51
浏览 34
已采纳

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

I'm trying to port an algorithm from Python to Go. The central part of it is a tree built using dicts, which should stay this way since each node can have an arbitrary number of children. All leaves are at the same level, so up the the lowest level the dicts contain other dicts, while the lowest level ones contain floats. Like this:

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

So while trying to port the code to Go while learning the language at the same time, this is what I started with to test the basic idea:

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

This works as expected, so the next step was to turn this into a routine that would take a "tree", a path, and a value. I chose the recursive approach and came up with this:

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

This is how I imagine the routine should be structured, but I can't get the line marked with "recursion" to work. There is either a compiler error, or a runtime error if I try to perform a type assertion on tree[node]. What would be the correct way to do this?

  • 写回答

2条回答 默认 最新

  • duanli0453 2012-06-05 15:22
    关注

    Go is perhaps not the ideal solution for generic data structures like this. The type assertions make it possible, but manipulating data in it requires more work that you are used to from python and other scripting languages.

    About your specific issue: You are missing a type assertion in the insert() call. The value of tree[node] is of type interface{} at that point. The function expects type map[string]interface{}. A type assertion will solve that.

    Here's a working example:

    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
    ", 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
        }
    }
    

    Note that I created a new type for the map. This makes the code a little easier to follow. I also use the same 'map[string]interface{}` for both tree nodes and leaves. If you want to get a float out of the resulting tree, another type assertion is needed:

    leaf := t["a"].(Tree)["b"]  // leaf is of type 'interface{}`.
    val := leaf.(float32)
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥20 TEC-9的数据通路实验
  • ¥15 ue5 .3之前好好的现在只要是激活关卡就会崩溃
  • ¥50 MATLAB实现圆柱体容器内球形颗粒堆积
  • ¥15 python如何将动态的多个子列表,拼接后进行集合的交集
  • ¥20 vitis-ai量化基于pytorch框架下的yolov5模型
  • ¥15 如何实现H5在QQ平台上的二次分享卡片效果?
  • ¥15 python爬取bilibili校园招聘网站
  • ¥30 求解达问题(有红包)
  • ¥15 请解包一个pak文件
  • ¥15 不同系统编译兼容问题