在Go语言中,我们可以使用type switch语句查询接口变量的真实数据类型,语法如下:
switch x.(type) {
// cases
}
x必须是接口类型。
来看一个详细的示例:
type Stringer interface {
String() string
}
var value interface{} // Value provided by caller.
switch str := value.(type) {
case string:
return str //type of str is string
case Stringer: //type of str is Stringer
return str.String()
}
语句switch中的value必须是接口类型,变量str的类型为转换后的类型。
If the switch declares a variable in the expression, the variable will have the corresponding type in each clause. It's also idiomatic to reuse the name in such cases, in effect declaring a new variable with the same name but a different type in each case.
如果我们只关心一种类型该如何做?如果我们知道值为一个string,只是想将它抽取出来该如何做?只有一个case的类型switch是可以的,不过也可以用类型断言(type assertions)。类型断言接受一个接口值,从中抽取出显式指定类型的值。其语法借鉴了类型switch子句,不过是使用了显式的类型,而不是type关键字,如下:
x.(T)
同样,x必须是接口类型。
str := value.(string)
上面的转换有一个问题,如果该值不包含一个字符串,则程序会产生一个运行时错误。为了避免这个问题,可以使用“comma, ok”的习惯用法来安全地测试值是否为一个字符串:
str, ok := value.(string)
if ok {
fmt.Printf("string value is: %q
", str)
} else {
fmt.Printf("value is not a string
")
}
如果类型断言失败,则str将依然存在,并且类型为字符串,不过其为零值,即一个空字符串。
我们可以使用类型断言来实现type switch的中例子:
if str, ok := value.(string); ok {
return str
} else if str, ok := value.(Stringer); ok {
return str.String()
}
这种做法没有多大实用价值。