无法从`[]interface{}`断言为`[]string`类型。

huangapple go评论71阅读模式
英文:

Unable to assert type `[]string` from `[]interface{}`

问题

我正在尝试处理从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

你知道为什么会发生这种情况吗?我该如何检索这些字符串?

英文:

I am trying to process some data retrieved from mongodb (mgo).

Unfortunately I am unable to assert the correct type for a list of strings.
The function I am working on is the following:

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
}

Unfortunately I am getting this following run-time panic:

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

Any idea on why this is happening? How can I retrieve those strings?

答案1

得分: 10

这是Go语言中的一个常见错误。

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

由于每个元素都是interface{}类型,而不是intFoo等类型,因此每个元素占用的内存更多(interface{}需要存储底层类型和包含的值)。因此,不能直接将[]interface值转换为[]string[]T值。

那么如何将[]interface{}转换为[]string呢?

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

package main

import "fmt"

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

    // 我们想将foo转换为[]string
    out := []string{}

    for _, v := range foo {
        // 使用类型断言,将v转换为字符串
        out = append(out, v.(string))
    }

    fmt.Println(out)
}

可运行的示例在这里

英文:

This is a common mistake with Go.

The reason is as follows: in Go []interface{} is not an interface, it's a slice type, whose elements are each the interface{} type.

Because each element is a interface{}, rather than, say, an int or Foo, more memory is taken up by each element (interface{} needs to store the underlying type, and the value contained). Therefore, it's not possible to directly convert a []interface value into a []string or []T value.

How do you convert []interface{} into []string, then?

The solution is quite simple — you convert each element.

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

Runnable example here.

答案2

得分: 4

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

stringSlice := make([]string, len(u["v"]))
for i, raw := range u["v"] {
    str, ok := raw.(string)
    if !ok {
        // 出现问题,不是我们期望的字符串
    }
    stringSlice[i] = str
}
英文:

A []interface{} will never be a []string. A slice has a backing array, and those elements have to be of a certain size. This may or may not be exactly correct depending on implementation details, but each element of an []interface{} will contain an interface{}. If all of these interface{} are "really" strings, they won't be the strings themselves but rather a wrapper over the string or a pointer to it. Thus you have to convert each individual element of a []interface{} yourself.

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
}

huangapple
  • 本文由 发表于 2014年5月10日 21:53:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/23581884.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定