关键字类型在交换机中使用时的含义是什么?

时间:2014-02-26 08:47:35

标签: go

我在golang中看到过这个代码的几个实例:

func process(node ast.Node) Foo {
    switch n := node.(type) {
        // ... removed for brevity
    }
}

ast.Node是一个界面。是node.(type)代码段来执行反射;找出界面的实际实现者?

2 个答案:

答案 0 :(得分:11)

是。它被称为类型开关。它允许您根据所传递的接口的实际类型执行代码。

我认为the official documentation及其示例很清楚:

  

交换机也可用于发现接口的动态类型   变量。这种类型的开关使用类型断言的语法   括号内的关键字类型。如果交换机声明了   在表达式变量中,变量将具有相应的   输入每个条款。在这种情况下重用名称也是惯用的   实际上,声明一个名称相同的新变量但是a   每种情况都有不同的类型。

var t interface{}
t = functionOfSomeType()
switch t := t.(type) {
default:
    fmt.Printf("unexpected type %T", t)       // %T prints whatever type t has
case bool:
    fmt.Printf("boolean %t\n", t)             // t has type bool
case int:
    fmt.Printf("integer %d\n", t)             // t has type int
case *bool:
    fmt.Printf("pointer to boolean %t\n", *t) // t has type *bool
case *int:
    fmt.Printf("pointer to integer %d\n", *t) // t has type *int
}

您不应该在正确输入的程序中经常使用它,但在您需要时它很方便。使用示例:假设您实现了数据库驱动程序,您可能必须根据Go变量的类型进行转换。这是an extract of the go-sql/mysql driver

// Scan implements the Scanner interface.
// The value type must be time.Time or string / []byte (formatted time-string),
// otherwise Scan fails.
func (nt *NullTime) Scan(value interface{}) (err error) {
    if value == nil {
        nt.Time, nt.Valid = time.Time{}, false
        return
    }

    switch v := value.(type) {
    case time.Time:
        nt.Time, nt.Valid = v, true
        return
    case []byte:
        nt.Time, err = parseDateTime(string(v), time.UTC)
        nt.Valid = (err == nil)
        return
    case string:
        nt.Time, err = parseDateTime(v, time.UTC)
        nt.Valid = (err == nil)
        return
    }

    nt.Valid = false
    return fmt.Errorf("Can't convert %T to time.Time", value)
}

答案 1 :(得分:2)

TYPE SWITCH

  

交换机也可用于发现接口的动态类型   变量。这种类型的开关使用类型断言的语法   括号内的关键字类型。如果交换机声明了   在表达式变量中,变量将具有相应的   输入每个条款。在这种情况下重用名称也是惯用的   实际上,声明一个名称相同的新变量但是a   每种情况都有不同的类型。

使用类型开关,您可以打开接口值的类型(仅限):

func do(v interface{}) string {
        switch u := v.(type) {
        case int:
                return strconv.Itoa(u*2) // u has type int
        case string:
                mid := len(u) / 2 // split - u has type string
                return u[mid:] + u[:mid] // join
        }
        return "unknown"
}

do(21) == "42"
do("bitrab") == "rabbit"
do(3.142) == "unknown"