Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Golang Type Switch: How to match a generic slice/array/map/chan?

Tags:

go

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...?

like image 392
likebike Avatar asked Aug 03 '16 15:08

likebike


People also ask

What is the use of Slice in Golang?

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, ...

What is a switch in Golang?

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.

What is a map in Golang?

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.

What is array data type in 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.


1 Answers

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)
}
like image 77
Bayta Darell Avatar answered Sep 30 '22 17:09

Bayta Darell