如何检查interface {}是否为切片

时间:2016-10-31 13:45:43

标签: go interface type-conversion slice

我在Go中的菜鸟:)所以我的问题可能是愚蠢的,但无法找到答案,所以。

我需要一个功能:

func name (v interface{}) {
    if is_slice() {
        for _, i := range v {
            my_var := i.(MyInterface)
            ... do smth
        }
    } else {
        my_var := v.(MyInterface)
        ... do smth
    }
}

如何在Go中执行is_slice?感谢任何帮助。

4 个答案:

答案 0 :(得分:7)

在您的情况下,type switch是最简单,最方便的解决方案:

func name(v interface{}) {
    switch x := v.(type) {
    case []MyInterface:
        fmt.Println("[]MyInterface, len:", len(x))
        for _, i := range x {
            fmt.Println(i)
        }
    case MyInterface:
        fmt.Println("MyInterface:", x)
    default:
        fmt.Printf("Unsupported type: %T\n", x)
    }
}

case分支枚举了可能的类型,而x变量中的type MyInterface interface { io.Writer } var i MyInterface = os.Stdout name(i) var s = []MyInterface{i, i} name(s) name("something else") 变量已经属于该类型,因此您可以使用它。

测试它:

MyInterface: &{0x1040e110}
[]MyInterface, len: 2
&{0x1040e110}
&{0x1040e110}
Unsupported type: string

输出(在Go Playground上尝试):

if x, ok := v.([]MyInterface); ok {
    // x is of type []MyInterface
    for _, i := range x {
        fmt.Println(i)
    }
} else {
    // x is not of type []MyInterface or it is nil
}

对于单一类型检查,您还可以使用type assertion

{{article.url}}

还有其他方法,使用包reflect你可以写一个更通用(和更慢)的解决方案,但如果你刚刚开始Go,你就不应该深入研究。

答案 1 :(得分:3)

icza's answer是正确的,但go creators不推荐

  

interface {}什么都没说

更好的方法可能是为您拥有的每种类型定义一个函数:

func name(v MyInterface) {
    // do something
}

func names(vs []MyInterface) {
    for _, v := range(vs) {
        name(v)
    }
}

答案 2 :(得分:0)

来自https://blog.golang.org/json

解码任意数据

考虑此存储在变量b中的JSON数据:

b := []byte(`{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}`)

在不知道此数据结构的情况下,我们可以使用Unmarshal将其解码为interface {}值:

var f接口{} 错误:= json.Unmarshal(b,&f) 此时,f中的Go值将是一个映射,该映射的键是字符串,并且其值本身存储为空接口值:

f = map[string]interface{}{
    "Name": "Wednesday",
    "Age":  6,
    "Parents": []interface{}{
        "Gomez",
        "Morticia",
    },
}

要访问此数据,我们可以使用类型断言来访问f的基础map [string] interface {}:

m := f.(map[string]interface{})

然后我们可以使用range语句遍历地图,并使用类型开关将其值作为其具体类型来访问:

for k, v := range m {
    switch vv := v.(type) {
    case string:
        fmt.Println(k, "is string", vv)
    case float64:
        fmt.Println(k, "is float64", vv)
    case []interface{}:
        fmt.Println(k, "is an array:")
        for i, u := range vv {
            fmt.Println(i, u)
        }
    default:
        fmt.Println(k, "is of a type I don't know how to handle")
    }
}

通过这种方式,您可以使用未知的JSON数据,同时仍可以享受类型安全的好处。

答案 3 :(得分:0)

is_slice 方法可以是这样的:

func IsSlice(v interface{}) bool {
    return reflect.TypeOf(v).Kind() == reflect.Slice
}

如果需要,也可以添加额外的 reflect.TypeOf(v).Kind() == reflect.Array 条件。