我在golang中看到过这个代码的几个实例:
func process(node ast.Node) Foo {
switch n := node.(type) {
// ... removed for brevity
}
}
ast.Node
是一个界面。是node.(type)
代码段来执行反射;找出界面的实际实现者?
答案 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)
交换机也可用于发现接口的动态类型 变量。这种类型的开关使用类型断言的语法 括号内的关键字类型。如果交换机声明了 在表达式变量中,变量将具有相应的 输入每个条款。在这种情况下重用名称也是惯用的 实际上,声明一个名称相同的新变量但是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"