遍历接口数组

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

Iterating over an array of interfaces

问题

我写了这段代码:

switch v.(type) {
    case []interface{}:
        fmt.Println(reflect.TypeOf(v))
        for index, element := range v {
            fmt.Println("Inside for")
        }
    default:
        fmt.Println("我不知道如何处理这个。")
}

现在,我的reflect.TypeOf(v)输出的类型是[]interface {}。但是,我无法遍历接口数组。我遇到了错误:cannot range over v (type interface {})。有人能解释一下为什么吗?还有,有什么解决方法吗?

英文:

I wrote the code:

switch v.(type) {
		case []interface{}:
			fmt.Println(reflect.TypeOf(v))
			for index, element := range v {
				fmt.Println("Inside for")
			}
		default:
			fmt.Println("I don't know how to handle this.")
		}

Now, my reflect.TypeOf(v) outputs the type as []interface {} . But, I'm not able to iterate over the array of interfaces. I encounter the error:cannot range over v (type interface {}). Could someone please explain me why ? Also, what's the workaround ?

答案1

得分: 9

type switch中,如果你想访问转换为适当类型的变量,只需使用类似switch x := v.(type)的语法,在switch的每个case中,x将是适当类型的值。规范中有一个例子。你甚至可以使用switch v := v.(type),在switch语句中会有一个被遮蔽的v的版本。

例如:

switch x := v.(type) {
case []interface{}:
        fmt.Printf("got %T\n", x)
        for i, e := range x {
                fmt.Println(i, e)
        }
default:
        fmt.Printf("I don't know how to handle %T\n", v)
}

<kbd>playground</kbd>

还要注意,当你只想打印变量的类型时,可以直接使用fmt.Printf%T,而不必直接使用reflect包。

最后,注意如果你有多个非默认子句,那么类型switch是你想要的,但是如果像你的例子一样,你只对一个特定类型感兴趣,那么你应该这样做:

if x, ok := v.([]interface{}); ok {
        fmt.Printf("got %T\n", x)
        for i, e := range x {
                fmt.Println(i, e)
        }
} else {
        fmt.Printf("I don't know how to handle %T\n", v)
}
英文:

In a type switch, if you wish to access the variable casted to the appropriate type just use something like switch x := v.(type) and in each case of the switch x will be of the appropriate value. The spec has an example of this. You can even do switch v := v.(type) and within the switch statement there will be a shadowed version of v.

E.g.:

switch x := v.(type) {
case []interface{}:
        fmt.Printf(&quot;got %T\n&quot;, x)
        for i, e := range x {
                fmt.Println(i, e)
        }
default:
        fmt.Printf(&quot;I don&#39;t know how to handle %T\n&quot;, v)
}

<kbd>playground</kbd>

Also note that you can just use "%T" with fmt.Printf instead of (directly) using the reflect package when you just want to print the type of a variable.

Finally, note that a type switch is what you want if you have multiple non-default clauses, but if, as in your example, you really only have one type you are interested in then instead you should do something like:

if x, ok := v.([]interface{}); ok {
        fmt.Printf(&quot;got %T\n&quot;, x)
        for i, e := range x {
                fmt.Println(i, e)
        }
} else {
        fmt.Printf(&quot;I don&#39;t know how to handle %T\n&quot;, v)
}

答案2

得分: 2

你可以始终使用v.([]interface{})。当我尝试解析需要作为接口处理的异构JSON对象时,我遇到了同样的问题。

尽管如此,在你的循环中,除非你事先了解数据的某些信息,否则可能无法起作用。

英文:

You can always use v.([]interface{}). I ran into the same problem when trying to parse hetrogeneous json objects that had to be treated as interfaces.

Although that might not work in your loop unless you know something about your data beforehand.

huangapple
  • 本文由 发表于 2015年3月10日 09:17:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/28954646.html
匿名

发表评论

匿名网友

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

确定