🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] 由于接口类型的值可以是任意一个实现了该接口的类型值,所以接口值除了需要记录具体值之外,还需要记录这个值属于的类型。 ![](https://img.kancloud.cn/75/11/7511d0613fb35af5239a70d2abcc3c81_665x299.png) 通过示例来理解接口值 ```go type Mover interface { Move() } type Dog struct { name string } func (d *Dog) Move() { fmt.Println("狗在跑~") } type Cat struct { name string } func (c *Cat) Move() { fmt.Println("猫在跑~") } func main() { var m Mover fmt.Println(m == nil) fmt.Printf("m: %v, type: %T\n", m, m) } // 运行结果 // true // m: <nil>, type: <nil> ``` ![](https://img.kancloud.cn/e0/ae/e0aecc8597c825c92a35c5b34f5d92e1_498x371.png) 从上述可知, 变量m值的类型和值都为 `nil`. 使用 `m == nil` 可以判断是否为空 >[danger] 如果接口的值为nil的话, 不能直接调用方法. 否则会 `panic: runtime error: invalid memory address or nil pointer dereference` 报错 接下来 Cat 结构体赋值给变量m的接口 ```go var m Mover m = &Cat{"旺财"} fmt.Println(m == nil) fmt.Printf("m: %v, type: %T\n", m, m) // 运行结果 // false // m: &{旺财}, type: *main.Cat ``` ![](https://img.kancloud.cn/00/d6/00d6bde036f4f0cd43b2cebe6bcaadb9_709x413.png) 从上述可知, 变量m值的类型和值都不为 `nil` >[warning] **注意**: 接口值保存的动态类型相同,但是这个动态类型不支持互相比较(比如切片),那么对它们相互比较时就会引发panic。