2016-08-03 45 views
4

如何使用Go Type Switch匹配通用切片,陣列,貼圖或通道?Golang類型切換:如何匹配通用切片/數組/地圖/ chan?

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包。

有沒有什麼方法可以使用類型開關來確定一個對象是一個切片/數組/地圖/陳/等...?

回答

11

類型開關使用特定類型。如果您無法枚舉交換機中的所有類型,則唯一的選擇是使用反射包。

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