接口
go
的接口是一种抽象的自定义类型
,没法直接实例化,它声明了一个或者多个方法的签名
;- 如果一个
struct
实现了一个接口定义的所有方法
,我们就说这个struct
实现了这个接口。注意这里的实现
是隐式
的,不用显示声明某个struct
实现了哪个接口
定义接口
Go
type interface_name interface {
method1()
method2()
...
}
实现接口
Go
type Sleeper interface {
sleep()
}
type Dog struct {
name string
age int
}
func (d Dog) sleep() {
fmt.Printf("%s在睡觉,它今年%d岁了\n", d.name, d.age)
}
type Cat struct {
name string
like string
}
func (c Cat) sleep() {
fmt.Printf("%s 在睡觉,它喜欢%s\n", c.name, c.like)
}
func main() {
dog_one := Dog {
name: "小黄",
age: 2,
}
// 小黄在睡觉,它今年2岁了
dog_one.sleep()
cat_one := Cat {
name: "kitty",
like: "爬",
}
// kitty 在睡觉,它喜欢爬
cat_one.sleep()
}
接口的多态
多态
就是同一个接口,对于不同的实例
执行不同的操作
;
如上面创建接口的例子,
Dog
结构体和Cat
结构体都实现了sleep
方法,做了不同的事情,这就是多态
Go
func main() {
...
dog_one.sleep()
cat_ont.sleep()
}
接口内部表示
可以把接口的内部看做
(type, value)
;type
是接口底层的具体类型
(Concrete Type);value
是具体类型的值
Go
type Sleeper interface {
sleep()
}
type Dog struct {
name string
age int
}
func (d Dog) sleep() {
fmt.Printf("%s在睡觉,它今年%d岁了\n", d.name, d.age)
}
func showInterfaceType(s Sleeper) {
fmt.Printf("接口s的类型为%T, 值为%v\n", s, s)
}
func main() {
var dog_two Sleeper
dog_two = Dog {
name: "小灰",
age: 6,
}
showInterfaceType(dog_two) // 接口s的类型为main.Dog, 值为{小灰 6}
dog_two.sleep() // 小灰在睡觉,它今年6岁了
}
空接口
空接口
是特殊形式的接口类型
,没有定义任何方法的接口就称为空接口;所有类型都至少实现了空接口,空接口表示为
interface{}
当函数的参数类型为
空接口
时,函数可以接受任何类型
的参数
Go
func emptyInterface(i interface{}) {
fmt.Printf("i的类型: %T, i的值: %v\n", i, i)
}
func main() {
name := "张环"
emptyInterface(name) // i的类型: string, i的值: 张环
age := 22
emptyInterface(age) // i的类型: int, i的值: 22
isBoss := true
emptyInterface(isBoss) // i的类型: bool, i的值: true
}
- 接口都有两个属性,一个是
值
,而另一个是类型
,对于空接口
来说,这两个属性都为nil
Go
func main() {
var empty_interface interface {}
// empty_interface 类型为<nil>, 值为<nil>
fmt.Printf("empty_interface 类型为%T, 值为%v\n", empty_interface, empty_interface)
}
- 使用空接口
interface{}
作为类型声明一个实例,这个实例就能承载任何类型
的值
Go
func main() {
var str interface {}
str = "张环"
fmt.Println(str) // 张环
str = 88
fmt.Println(str) // 88
str = true
fmt.Println(str) // true
str = []string{"张环", "李朗"}
fmt.Println(str) // [张环 李朗]
str = map[string]int{
"name": 2,
"age": 22,
}
fmt.Println(str) // map[age:22 name:2]
}
- 也可以定义一个接收任何类型的
array
、slice
、map
、strcut
Go
func main() {
any_type_value := make([]interface{}, 5)
any_type_value[0] = "张环"
any_type_value[1] = 22
any_type_value[2] = map[int]int{1: 10, 2: 20}
any_type_value[3] = []int{2, 22, 222}
for idx, value := range any_type_value {
fmt.Printf("第%d个值为%v\n", idx, value)
// 第0个值为张环
// 第1个值为22
// 第2个值为map[1:10 2:20]
// 第3个值为[2 22 222]
// 第4个值为<nil>
}
}
类型断言
类型断言用于
提取接口的底层值
(Underlying Value);使用
interface.(Type)
可以获取接口的底层值,其中接口interface
的具体类型是Type
;
Go
func assertType(i interface{}) {
switch i.(type) {
case int:
// int类型
fmt.Println("int类型")
case string:
// string类型
fmt.Println("string类型")
case bool:
// 布尔(bool)类型
fmt.Println("布尔(bool)类型")
default:
fmt.Println("未知类型unknown")
}
}
func main() {
assertType(1)
assertType("张环")
assertType(false)
}