【问题标题】:Golang Type Switch: How to match a generic slice/array/map/chan?Golang 类型切换:如何匹配一个通用的 slice/array/map/chan?
【发布时间】:2016-12-09 10:35:08
【问题描述】:

如何使用 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: %#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))
}

这是输出:

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,那么它适用于我给定的示例,但不可能提前知道所有输入类型,所以我需要一个更通用的解决方案。如果类型开关能够处理这个问题,我想避免使用 reflect 包。

有没有什么方法可以使用类型开关来判断一个对象是否是切片/数组/映射/chan/etc...?

【问题讨论】:

    标签: go


    【解决方案1】:

    类型开关适用于特定类型。如果不能枚举开关中的所有类型,那么唯一的选择就是使用反射包。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-08-31
      • 2013-09-13
      • 2014-08-08
      • 1970-01-01
      • 2021-11-16
      • 2019-10-23
      • 1970-01-01
      相关资源
      最近更新 更多