检查接口{}是否是某物的切片([]接口{})

  • 本文关键字:接口 切片 是否是 go
  • 更新时间 :
  • 英文 :

func main() {
strSlice := []string{"a", "b", "c"}
f(strSlice)
}
func f(slice interface{}) {
anySlice, isSlice := slice.([]interface{})
fmt.Printf("isSlice = %t, anySlice = %#vn", isSlice, anySlice)
}

游乐场:https://play.golang.org/p/UN25mIOqmOd

该程序打印isSlice = false, anySlice = []interface {}(nil).为什么? 我本来希望这种类型的断言是可能的。

并且:有没有办法动态检查接口{}是某物的一部分?

类型断言失败,因为[]string不是[]interface{}。有关详细信息,请参阅常见问题解答。

使用反射包确定接口中的具体值是否为切片:

func f(slice interface{}) {
isSlice := reflect.ValueOf(slice).Kind() == reflect.Slice
fmt.Printf("isSlice = %t, anySlice = %#vn", isSlice, slice)
}

在操场上运行它。

还可以使用反射包循环访问值:

v := reflect.ValueOf(slice)
isSlice := v.Kind() == reflect.Slice
if isSlice {
for i := 0; i < v.Len(); i++ {
fmt.Printf("%d: %vn", i, v.Index(i).Interface())
}
}

在操场上运行它。

此程序打印isSlice = false, anySlice = []interface {}(nil)。为什么?

因为slice不包含[]interface{},所以它包含一个[]string。这些是不同的类型,Go 没有给你任何协变容器类型的概念。

并且:有没有办法动态检查接口{}是某物的一部分?

是的,您可以使用反射:

func f(slice interface{}) {
typ := reflect.TypeOf(slice)
if typ.Kind() == reflect.Slice {
elemType := typ.Elem()
fmt.Println("slice of", elemType.Name())
} else {
fmt.Println("not a slice")
}
}

实际上,对这些信息任何事情可能会更复杂。

请注意,如果您将断言更改为:slice.([]string)事情将按预期工作。当你考虑 Go 如何处理stringinterface{}类型断言时,这是有意义的。以下情况将导致编译错误:

package main
func main() {
s := "some string"
i := s.(interface{})
}

错误:

invalid type assertion: s.(<inter>) (non-interface type string on left)

[]string[]interface{}也应该失败是有道理的,因为 Go 不会将字符串视为interface{}类型。

最新更新