如何使用Go Type Switch来匹配通用切片、数组、映射或通道?
package main
import (
"fmt"
"reflect"
)
func WhatIsIt(x interface{}) {
switch X := x.(type) {
case bool:
fmt.Printf("Type Switch says %#v is a boolean.n", X)
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
fmt.Printf("Type Switch says %#v is an integer.n", X)
case float32, float64, complex64, complex128:
fmt.Printf("Type Switch says %#v is a floating-point.n", X)
case string:
fmt.Printf("Type Switch says %#v is a string.n", X)
case []interface{}:
fmt.Printf("TypeSwitch says %#v is a slice.n", X)
case map[interface{}]interface{}:
fmt.Printf("TypeSwitch says %#v is a map.n", X)
case chan interface{}:
fmt.Printf("TypeSwitch says %#v is a channel.n", X)
default:
switch reflect.TypeOf(x).Kind() {
case reflect.Slice, reflect.Array, reflect.Map, reflect.Chan:
fmt.Printf("TypeSwitch was unable to identify this item. Reflect says %#v is a slice, array, map, or channel.n", X)
default:
fmt.Printf("Type handler not implemented: %#vn", X)
}
}
}
func main() {
WhatIsIt(true)
WhatIsIt(1)
WhatIsIt(1.5)
WhatIsIt("abc")
WhatIsIt([]int{1,2,3})
WhatIsIt(map[int]int{1:1, 2:2, 3:3})
WhatIsIt(make(chan int))
}
这是输出:
Type Switch says true is a boolean.
Type Switch says 1 is an integer.
Type Switch says 1.5 is a floating-point.
Type Switch says "abc" is a string.
TypeSwitch was unable to identify this item. Reflect says []int{1, 2, 3} is a slice, array, map, or channel.
TypeSwitch was unable to identify this item. Reflect says map[int]int{1:1, 2:2, 3:3} is a slice, array, map, or channel.
TypeSwitch was unable to identify this item. Reflect says (chan int)(0x104320c0) is a slice, array, map, or channel.
从输出中可以看到,case []interface{}
与我发送的切片不匹配。我需要改用reflect
包。
如果我显式地编写case []int
,那么它适用于我给定的示例,但不可能提前知道所有的输入类型,所以我需要一个更通用的解决方案。如果Type Switch能够处理此问题,我希望避免使用reflect
包。
是否有任何方法可以使用类型开关来确定对象是否为切片/数组/映射/通道等。。。?
类型开关适用于特定类型。如果不能枚举交换机中的所有类型,那么唯一的选择就是使用反射包。
v := reflect.ValueOf(x)
switch v.Kind() {
case reflect.Bool:
fmt.Printf("bool: %vn", v.Bool())
case reflect.Int, reflect.Int8, reflect.Int32, reflect.Int64:
fmt.Printf("int: %vn", v.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint32, reflect.Uint64:
fmt.Printf("int: %vn", v.Uint())
case reflect.Float32, reflect.Float64:
fmt.Printf("float: %vn", v.Float())
case reflect.String:
fmt.Printf("string: %vn", v.String())
case reflect.Slice:
fmt.Printf("slice: len=%d, %vn", v.Len(), v.Interface())
case reflect.Map:
fmt.Printf("map: %vn", v.Interface())
case reflect.Chan:
fmt.Printf("chan %vn", v.Interface())
default:
fmt.Println(x)
}