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

huangapple go评论71阅读模式
英文:

How to check if interface{} is a slice

问题

我是Go的新手 如何检查 interface{} 是否为切片类型 所以我的问题可能很愚蠢,但是找不到答案,所以。

我需要一个函数:

func name (v interface{}) {
    if is_slice() {
        for _, i := range v {
            my_var := i.(MyInterface)
            ... 做一些事情
        }
    } else {
        my_var := v.(MyInterface)
        ... 做一些事情
    }
}

在Go中如何实现is_slice?感谢任何帮助。

英文:

I'm noob in Go 如何检查 interface{} 是否为切片类型 so my question may be stupid, but can't find answer, so.

I need a function:

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

How can I do is_slice in Go? Appreciate any help.

答案1

得分: 16

is_slice方法可以像这样:

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

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

英文:

The is_slice method can be something like this:

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

Can also put additional condition of reflect.TypeOf(v).Kind() == reflect.Array if required.

答案2

得分: 15

在你的情况下,类型开关是最简单和最方便的解决方案:

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("不支持的类型:%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")

输出结果(在 Go Playground 上尝试):

MyInterface: &{0x1040e110}
[]MyInterface, len: 2
&{0x1040e110}
&{0x1040e110}
不支持的类型:string

对于单个类型检查,你还可以使用 类型断言

if x, ok := v.([]MyInterface); ok {
    // x 是类型 []MyInterface
    for _, i := range x {
        fmt.Println(i)
    }
} else {
    // x 不是类型 []MyInterface 或者为 nil
}

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

英文:

In your case the type switch is the simplest and most convenient solution:

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

The case branches enumerate the possible types, and inside them the x variable will already be of that type, so you can use it so.

Testing it:

type MyInterface interface {
	io.Writer
}

var i MyInterface = os.Stdout
name(i)
var s = []MyInterface{i, i}
name(s)
name("something else")

Output (try it on the Go Playground):

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

For a single type check you may also use type assertion:

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
}

There are also other ways, using package reflect you can write a more general (and slower) solution, but if you're just starting Go, you shouldn't dig into reflection yet.

答案3

得分: 3

icza的答案是正确的,但不被Go的创建者推荐:

> interface{} 什么都不表示

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

func name(v MyInterface) {
    // 做一些操作
}

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

icza's answer is correct, but is not recommended by go creators:

> interface{} says nothing

A better approach may be to define a function for each type you have:

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

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

答案4

得分: 0

https://blog.golang.org/json

解码任意数据

考虑以下 JSON 数据,存储在变量 b 中:

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

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

var f interface{}
err := 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, "是字符串", vv)
    case float64:
        fmt.Println(k, "是 float64", vv)
    case []interface{}:
        fmt.Println(k, "是一个数组:")
        for i, u := range vv {
            fmt.Println(i, u)
        }
    default:
        fmt.Println(k, "是一个我不知道如何处理的类型")
    }
}

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

英文:

From https://blog.golang.org/json

Decoding arbitrary data

Consider this JSON data, stored in the variable b:

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

Without knowing this data's structure, we can decode it into an interface{} value with Unmarshal:

var f interface{}
err := json.Unmarshal(b, &f)
At this point the Go value in f would be a map whose keys are strings and whose values are themselves stored as empty interface values:

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

To access this data we can use a type assertion to access f's underlying map[string]interface{}:

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

We can then iterate through the map with a range statement and use a type switch to access its values as their concrete types:

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

In this way you can work with unknown JSON data while still enjoying the benefits of type safety.

huangapple
  • 本文由 发表于 2016年10月31日 21:45:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/40343471.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定