1

我正在尝试处理从mongodb ( mgo ) 检索到的一些数据。

不幸的是,我无法为字符串列表断言正确的类型。我正在处理的功能如下:

func generate_version_histogram(userStats []interface{}) map[string]int {
    var histogram map[string]int
    for _, _u := range userStats {
        u := _u.(bson.M)
        for _, version := range (u["v"]).([]string) {
            if _, alreadyhere := histogram[version]; alreadyhere {
                histogram[version] += 1
            } else {
                histogram[version] = 1
            }
        }
    }
    return histogram
}

不幸的是,我在运行时出现恐慌:

interface conversion: interface is []interface {}, not []string

知道为什么会这样吗?我怎样才能检索这些字符串?

4

2 回答 2

10

这是 Go 的常见错误。

原因如下:在 Go[]interface{}中不是接口,它是一个 slice 类型,其元素都是interface{}类型。

因为每个元素都是 a interface{},而不是intor Foo,所以每个元素占用了更多内存(interface{}需要存储基础类型和包含的值)。因此,无法直接将[]interface值转换为 a[]string[]T值。

那你怎么转换[]interface{}[]string?

解决方案非常简单——转换每个元素。

package main

import "fmt"

func main() {
    foo := []interface{}{"a", "b", "c"}

    // we want to convert foo to a []string
    out := []string{}

    for _, v := range foo {
        // using a type assertion, convert v to a string
        out = append(out, v.(string))
    }

    fmt.Println(out)
}

可运行的例子在这里。

于 2014-05-10T14:14:14.447 回答
4

A[]interface{}永远不会是[]string. 切片有一个后备数组,这些元素必须具有一定的大小。这可能会或可能不会完全正确,具体取决于实现细节,但 an 的每个元素都[]interface{}将包含一个interface{}. 如果所有这些interface{}都是“真正的”字符串,它们将不是字符串本身,而是字符串的包装器或指向它的指针。因此,您必须自己转换 a 的每个单独元素[]interface{}

stringSlice := make([]string, len(u["v"]))
for i,raw := range u["v"] {
    str,ok := raw.(string)
    if !ok {
        // Something is wrong, not a string like we expected
    }
    stringSlice[i] = str
}
于 2014-05-10T14:10:17.130 回答