How can I use a Go Type Switch to match a generic slice, array, map, or channel?
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: %#v\n", 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))
}
Here is the output:
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.
As you can see from the output, the case []interface{}
fails to match the slice that I send in. I need to resort to using the reflect
package instead.
If I explicitly write case []int
, then it works for my given example, but it's impossible to know all the input types ahead of time, so I need a more general solution. I want to avoid using the reflect
package if the Type Switch is able to handle this.
Is there any way to use the Type Switch to determine if an object is a slice/array/map/chan/etc...?
Slices in Golang. In Go language slice is more powerful, flexible, convenient than an array, and is a lightweight data structure. Slice is a variable-length sequence which stores elements of a similar type, you are not allowed to store different type of elements in the same slice. It is just like an array having an index value and length, ...
The switch can have multiple value cases for different types and is used to select a common block of code for many similar cases. Note: Golang does not needs a ‘break’ keyword at the end of each case in the switch.
The map data type is an associative data type and is also an unordered collection. the concept of using maps in golang is key-value based. If the array or slice uses an index in the form of a number, the data type map index is a key. and the key for each element must be unique The code above is an example of applying the map to Golang.
Array The array data type is a structured data type that can store a lot of data. usually the data stored has the same type. In golang, the number of array elements will be set before the array elements are defined. and each element of the array has an index which will refer to the position of the element in the array.
Type switches work with specific types. If you cannot enumerate all of the types in the switch, then the only option is to use the reflect package.
v := reflect.ValueOf(x)
switch v.Kind() {
case reflect.Bool:
fmt.Printf("bool: %v\n", v.Bool())
case reflect.Int, reflect.Int8, reflect.Int32, reflect.Int64:
fmt.Printf("int: %v\n", v.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint32, reflect.Uint64:
fmt.Printf("int: %v\n", v.Uint())
case reflect.Float32, reflect.Float64:
fmt.Printf("float: %v\n", v.Float())
case reflect.String:
fmt.Printf("string: %v\n", v.String())
case reflect.Slice:
fmt.Printf("slice: len=%d, %v\n", v.Len(), v.Interface())
case reflect.Map:
fmt.Printf("map: %v\n", v.Interface())
case reflect.Chan:
fmt.Printf("chan %v\n", v.Interface())
default:
fmt.Println(x)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With