【问题标题】:How to iterate over an []interface{} in Go如何在 Go 中迭代 []interface{}
【发布时间】:2018-12-12 19:54:34
【问题描述】:

我正在努力获取以下接口的键和值,这是 JSON 封送Execute 返回的结果的结果,如this example 所示:

[
    [
        {
            "id": 36,
            "label": "TestThing",
            "properties": {
                "schema__testBoolean": [
                    {
                        "id": 40,
                        "value": true
                    }
                ],
                "schema__testInt": [
                    {
                        "id": 39,
                        "value": 1
                    }
                ],
                "schema__testNumber": [
                    {
                        "id": 38,
                        "value": 1.0879834
                    }
                ],
                "schema__testString": [
                    {
                        "id": 37,
                        "value": "foobar"
                    }
                ],
                "uuid": [
                    {
                        "id": 41,
                        "value": "7f14bf92-341f-408b-be00-5a0a430852ee"
                    }
                ]
            },
            "type": "vertex"
        }
    ]
]

reflect.TypeOf(result) 结果为:[]interface{}

我用它来循环数组:

s := reflect.ValueOf(result)
for i := 0; i < s.Len(); i++ {
  singleVertex := s.Index(i).Elem() // What to do here?
}

但我遇到了以下错误:

reflect.Value.Interface:无法返回未导出的值 字段或方法

【问题讨论】:

  • 如果不需要使用reflection,那么您应该避免使用它并遍历[]interface{}
  • 那么,如果我不知道结构,我会使用反射吗?
  • @BobvanLuijt:基本上。

标签: go interface type-assertion


【解决方案1】:

如果您知道这是您的数据结构,则根本没有理由使用反射。只需使用类型断言:

for key, value := range result.([]interface{})[0].([]interface{})[0].(map[string]interface{}) {
    // key == id, label, properties, etc
}

【讨论】:

    【解决方案2】:

    要获取接口的底层值,请使用类型断言。详细了解 Type assertion 及其工作原理。

    package main
    
    import (
        "fmt"
    )
    
    func main() {
         res, err := g.Execute( // Sends a query to Gremlin Server with bindings
               "g.V(x)",
                map[string]string{"x": "1234"},
                map[string]string{},
         )
         if err != nil {
              fmt.Println(err)
              return
         }
         fetchValue(res)
    }
    
    func fetchValue(value interface{}) {
        switch value.(type) {
        case string:
            fmt.Printf("%v is an interface \n ", value)
        case bool:
            fmt.Printf("%v is bool \n ", value)
        case float64:
            fmt.Printf("%v is float64 \n ", value)
        case []interface{}:
            fmt.Printf("%v is a slice of interface \n ", value)
            for _, v := range value.([]interface{}) { // use type assertion to loop over []interface{}
                fetchValue(v)
            }
        case map[string]interface{}:
            fmt.Printf("%v is a map \n ", value)
            for _, v := range value.(map[string]interface{}) { // use type assertion to loop over map[string]interface{}
                fetchValue(v)
            }
        default:
            fmt.Printf("%v is unknown \n ", value)
        }
    }
    

    【讨论】:

    • 这只是一个例子,我主要关心的是解组然后使用类型断言来获取基础值。我只是使用递归来获取 interface{} 切片的值。我以 json 为例,因为 OP 在他的问题中给出了 json。
    • OP 解释说他的result 变量是Execute 方法的输出,它既不返回也不消耗JSON。也许数据库中的数据存储为 JSON,但无法通过 Go 客户端库以这种形式访问,因此使用 json.Unmarshal 回答是不可回答的。
    • 好的,但是在任何情况下都可以使用递归来获取interface{} 的切片的值。因此,我根据您的信息编辑了我的答案。
    猜你喜欢
    • 1970-01-01
    • 2017-04-10
    • 2023-01-11
    • 2023-01-16
    • 1970-01-01
    • 2015-03-31
    • 1970-01-01
    • 1970-01-01
    • 2020-07-17
    相关资源
    最近更新 更多