Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterating over an array of interfaces

Tags:

go

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 ?

like image 848
Jerry Ajay Avatar asked Dec 25 '22 22:12

Jerry Ajay


1 Answers

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

playground

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("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)
}
like image 96
Dave C Avatar answered Jan 09 '23 07:01

Dave C