range over interface{} which stores a slice
Well I used reflect.ValueOf
and then if it is a slice you can call Len()
and Index()
on the value to get the len
of the slice and element at an index. I don't think you will be able to use the range operate to do this.
package main
import "fmt"
import "reflect"
func main() {
data := []string{"one","two","three"}
test(data)
moredata := []int{1,2,3}
test(moredata)
}
func test(t interface{}) {
switch reflect.TypeOf(t).Kind() {
case reflect.Slice:
s := reflect.ValueOf(t)
for i := 0; i < s.Len(); i++ {
fmt.Println(s.Index(i))
}
}
}
Go Playground Example: http://play.golang.org/p/gQhCTiwPAq
You don't need to use reflection if you know which types to expect. You can use a type switch, like this:
package main
import "fmt"
func main() {
loop([]string{"one", "two", "three"})
loop([]int{1, 2, 3})
}
func loop(t interface{}) {
switch t := t.(type) {
case []string:
for _, value := range t {
fmt.Println(value)
}
case []int:
for _, value := range t {
fmt.Println(value)
}
}
}
Check out the code on the playground.
Expanding on the answer provided by masebase, you could generalize the iteration on an interface{}
slice with a function like this:
func forEachValue(ifaceSlice interface{}, f func(i int, val interface{})) {
v := reflect.ValueOf(ifaceSlice)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() != reflect.Slice {
panic(fmt.Errorf("forEachValue: expected slice type, found %q", v.Kind().String()))
}
for i := 0; i < v.Len(); i++ {
val := v.Index(i).Interface()
f(i, val)
}
}
Then, you use it like this:
func main() {
data := []string{"one","two","three"}
test(data)
moredata := []int{1,2,3}
test(data)
}
func test(sliceIface interface{}) {
forEachValue(sliceIface, func(i int, value interface{}) {
fmt.Println(value)
}
}