上一篇学习了接口的定义以及如何实现一个接口。接下来继续学习接口的相关知识。
空接口
空接口表示没有任何约束,因此任何类型变量都可以实现空接口。
用空接口可以表示任何数据类型。
package main
import "fmt"
// 空接口
type AllType interface {
}
func main () {
var at AllType
str := "hello world"
// 将 string 类型变量 str 赋值给 AllType 类型变量 at,但是该变量实际引用的依然是 string 类型的实例
at = str
fmt.Printf("value:%v type:%T\n", at, at) // value:hello world type:string
num := 32
// 将 int 类型变量 num 赋值给 AllType 类型变量 at,但是该变量实际引用的依然是 int 类型的值
at = num
fmt.Printf("value:%v type:%T\n", at, at) // value:32 type:int
flag := true
// 将 bool 类型变量 flag 赋值给 AllType 类型变量 at,但是该变量实际引用的依然是 bool 类型的值
at = flag
fmt.Printf("value:%v type:%T", at, at) // value:true type:bool
}
如上代码展示了,任何类型的变量都可以给空接口类型的变量赋值。虽然空接口类型的变量可以接受任意类型,但是变量实际引用的地址还是指向原来变量。
因为空接口可以接受任意类型,所以当空接口作为函数的参数类型时,该函数的参数可以接受任意类型的变量作为实参。
类型推断
类型推断可将接口变量还原为原始类型,或用来判断是否实现了某个更具体的接口类型。
当要判断空接口中值的类型时,可以使用类型断言
x.(T)
- x:表示类型为interface{}的变量
- T: 表示断言x可能是的类型
package main
import "fmt"
type animal interface {
speak() string
}
type bird interface {
animal
fly()
}
type Magpie struct {
}
func(magpie Magpie) speak() string {
return "叽叽喳喳"
}
func(magpie Magpie) fly() {
fmt.Println("飞~~~~")
}
func eat(a animal) {
fmt.Println("干饭去吧")
}
func main() {
var magpie Magpie
var a animal = magpie
v, ok := a.(Magpie)
if ok {
fmt.Printf("%v 是一个 Magpie 类型\n", v) // {} 是一个 Magpie 类型
} else {
fmt.Println("断言失败")
}
}
还是通过之前的代码例子来演示。可以发现可以通过 x.(T) 来判断当前变量 a 是否是 T 类型的实例。