# 07.3 类型断言

类型断言的表示方法是`x.(T)`，其中`x`是接口类型的变量，`T`是要判断的类型。也就是说，存储在`x`接口类型的变量中的实际值是`T`类型，并且`T`必须满足`x`的接口类型变量！以下的段落和代码示例，将澄清**类型断言**的这个相对不容易理解的概念。

类型断言做两件事：第一件事是检查接口类型变量是否是特定的类型，这样使用时，类型断言返回两个值：基础值和`bool`值。虽然基础值是您可能想要使用的值，但是布尔值告诉您类型断言是否成功！

类型断言所做的第二件事是允许您使用存储在接口中的具体值或将其分配给新变量。这意味着如果接口中有一个`int`变量，可以使用类型断言获取该值。

但是，如果类型断言不成功，并且没有处理该失败，那么您的程序将触发`panic`异常。接下来我们分两部分介绍`assertion.go`程序。第一部分包含以下Go代码：

> ```go
> package main
>
> import (
>     "fmt"
> )
>
> func main() {
>     var myInt interface{} = 123
>     k, ok := myInt.(int)
>     if ok {
>         fmt.Println("Success:", k)
>     }
>     v, ok := myInt.(float64)
>     if ok {
>         fmt.Println(v)
>     } else {
>         fmt.Println("Failed without panicking!")
>     }
> ```

首先，声明`myInt`变量，该变量具有动态类型`int`和值`123`。然后使用类型断言测试两次`myInt`变量的接口类型 — 分别是`int`类型和`float64`类型。

由于`myInt`变量不包含`float64`值，因此类型断言`myInt.(float64)`执行时，如果没有恰当的处理，则会引发错误。因此在这种情况下，使用`ok`变量来判断类型断言是否成功，将使程序免于`panic`异常。

以下Go代码是`assertion.go`程序的第二部分：

> ```go
>     i := myInt.(int)
>     fmt.Println("No cheking:", i)
>     j := myInt.(bool)
>     fmt.Println(j)
> }
> ```

这里有两种类型的断言。第一个类型断言是成功的，因此不会有任何问题。但是，让我们进一步回顾一下这个特定类型的断言。变量`i`的类型为`int`，其值为`123`，存储在`myInt`中。因此由于`int`满足`myInt`接口，并且`myInt`接口不需要实现接口函数，所以`myInt.(int)`的值是一个`int`值。

然而第二个类型断言`myInt.(bool)`将触发`panic`异常，因为`myInt`的基础值不是布尔值（`bool`）。因此执行`assertion.go`将生成以下输出：

> ```
> $ go run assertion.go
> Success: 123
> Failed without panicking!
> No cheking: 123
> panic: interface conversion: interface {} is int, not bool
>
> goroutine 1 [running]:
> main.main()
>       /Users/mtsouk/Desktop/masterGo/ch/ch7/code/assertion.go:25 +0x1d9
> exit status 2
> ```

程序的执行结果明确的给出了触发`panic`异常的原因：`interface{} is int, not bool`。

一般来说，在使用接口时，也应该使用类型断言。您马上会在`useInterface.go`程序中看到更多类型断言的使用案例。
