'Clubbing values of type switch [duplicate]

Following code is working fine

var requestMap map[string]interface{}
for _, value := range requestMap {
    switch v := value.(type) {
    case []interface{}:
        if len(v) == 0 {
            // if is empty then no need to throw NA
            return http.StatusOK, nil
        }
    case string:
        if len(v) == 0 {
            // if is empty then no need to throw NA
            return http.StatusOK, nil
        }
    }
}

But following code is giving invalid argument for len function, I have read this question

var requestMap map[string]interface{}
for _, value := range requestMap {
    switch v := value.(type) {
    case []interface{}, string:
        if len(v) == 0 {
            // if is empty then no need to throw NA
            return http.StatusOK, nil
        }
    }
}

Isn't this case statement enough to identify []interface{} or string as value type ? Why is it still considering interface{} as parameter of len()



Solution 1:[1]

If you list multiple types in a case of a type switch, the static type of the switch variable will be of the type of the original variable. Spec: Switch statements:

In clauses with a case listing exactly one type, the variable has that type; otherwise, the variable has the type of the expression in the TypeSwitchGuard.

So if the switch expression is v := value.(type), the of v in the matching case (listing multiple types) will be the type of value, in your case it will be interface{}. And the builtin len() function does not allow to pass values of type interface{}.

Solution 2:[2]

This is because in the case of the type switch, the v should be converted to a slice of interface ([]interface) and to a string at the same time. The compiler can't decide which to use, so it revert back the value to interface{}, since it can be anything.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Fenistil