Golang不能对一个interface{}进行range

1,997 阅读1分钟

直接看一个demo:

func main() {
	sli := []interface{}{[]int{1, 2, 3, 4}}
	for _, v := range sli { //sli是interface{}类型切片
		for _, val := range v { //v是interface{}类型 cannot range over v (type interface {})
			fmt.Println(val)
		}
	}
}

D:\workspace\go\src\test>go run main.go
# command-line-arguments
.\main.go:50:17: cannot range over v (type interface {}) 

这段代码在for _, val := range v 的时候编译不通过,大概意思是:range不能作用于interface{]类型的v。

刚开始的时候我一直以为v是一个切片([]int{1, 2, 3, 4}),所以一直认为对切片进行range是没有问题的。甚至我还去打印了v的类型:

func main() {
	sli := []interface{}{[]int{1, 2, 3, 4}}
	for _, v := range sli { //sli是interface{}类型切片
		ty := reflect.ValueOf(v)
		fmt.Println(ty.Kind()) //slice
	}
}

从结果来看v是切片,那为什么对v进行range会编译错误呢?

我们再看看第一段代码,我们定义了一个切片sli,它是interface{}类型,它也就一个值:[]int{1, 2, 3, 4},也就是说sli里面的值类型都是interface{}类型,sli自己本身就是interface{}的切片,所以第一个range sli是没有问题的,但是v他是interface{}类型【注意:interface{}类型切片与interface{}类型的区别】在编译阶段range并不能知道它是[]int类型,至于第二个例子代码打印是切片类型,因为去掉了v的range,编译通过了,再打印自然是实际的数据类型。如果加上还是编译不通过:

sli := []interface{}{[]int{1, 2, 3, 4}}
	for _, v := range sli {
		ty := reflect.ValueOf(v)
		fmt.Println(ty.Kind())
		for _, val := range v {
			fmt.Println(val)
		}
	}

D:\workspace\go\src\test>go run main.go
# command-line-arguments
.\main.go:51:17: cannot range over v (type interface {}) 

那如何改呢?看下面【断言一下,代码正常运行】:

package main

import "fmt"

func main() {
	sli := []interface{}{[]int{1, 2, 3, 4}}
	for _, v := range sli { //sli是interface{}类型切片
		for _, val := range v.([]int) { //断言一下
			fmt.Println(val)
		}
	}
}