2016-08-03 5 views
4

Wie kann ich einen Go-Typ-Switch verwenden, um einen generischen Slice, Array, Map oder Channel zuzuordnen? HierGolang Type Switch: Wie wird ein generischer Slice/Array/Karte/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)) 
} 

ist die Ausgabe:

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. 

Wie Sie aus der Ausgabe sehen können, die case []interface{} nicht die Scheibe übereinstimmen, die ich in schicke ich brauche stattdessen mit dem reflect Paket zu greifen..

Wenn ich explizit schreibe case []int, dann funktioniert es für mein gegebenes Beispiel, aber es ist unmöglich, alle Eingabearten im Voraus zu wissen, also brauche ich eine allgemeinere Lösung. Ich möchte vermeiden, das reflect Paket zu verwenden, wenn der Type Switch damit umgehen kann.

Gibt es eine Möglichkeit, mit dem Type Switch festzustellen, ob ein Objekt ein Slice/Array/Map/Chan/etc ... ist?

Antwort

11

Typschalter arbeiten mit bestimmten Typen. Wenn Sie nicht alle Typen im Switch aufzählen können, ist die einzige Option, das Reflect-Paket zu verwenden.

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