Go是强类型的语言,有了接口带来了很大的灵活性。
接口类型就是一系列方法的集合,某类型只要实现了这些方法,就可以传给该接口。
定义一个接口rapper
,只要会唱(sing), 跳(dance)它就是一个rappper
我们创建一个类型,它有sing
, dance
的方法
再创建一个函数,它接收rapper
作为参数, 调用rapper
的sing
,dance
方法
我们可以常见一个person
类型变量,把它传人rap
函数,因为person
已经实现了rapper
接口的所有方法,可以把person
叫做一个rapper
完整代码:
运行,输出
接口是隐性实现的,只要该类型实现了该接口的所有方法,就实现了该接口,可以赋值给该接口,不需要显示声明实现了该接口。
接口的最大作用是解耦代码。使依赖和实现分离。
假设我有一个俱乐部club
它需要一个rapper
俱乐部会举办了一个演出,演出期间rapper
会唱sing
和跳dance
, 用一个show
方法实现:
好的,现在让club开起来, 使用person
类型作为rapper
完整代码:
运行,输出
到这里,还体现不出接口的好处。设想一下,有一天person
病了,来不了了,club
办不了了怎么办?
这时我们可以通过接口无缝切换到另一个rapper
。
实现另一个rapper
, 一只猫也可以成为rapper
:
好的,把club
开起来
完整代码:
运行,输出
接口就是这样,让依赖和实现分离,你可以切换自如。把接口想象成你电脑的USB
接口,只要形状一样,就可以插进来。这样一个接口可以同时支持键盘,鼠标,麦克风等不同功能。如果一个设备坏了,例如鼠标坏了,直接换另一个新的鼠标插入就好,不需要拆开电脑换。
有两个接口: rapper 和 programmer
你可以组合成另一个接口rapprogrammer
其实就是等价于
实现了rapprogrammer
接口也就实现了rapper
和programmer
接口,很好理解对吧,只要类型实现了某接口的所有方法就是实现了该接口。
我们经常使用any
类型,可以存放所有类型的值,如何做到的?
Go全局设置了这个:
any
就是空接口interface{}
的别名。空接口没有方法集,所有类型都实现这个接口,因为没有方法要实现嘛!很巧妙,是不是。
我们知道,接口的零值是nil
输出
输出
其实,所有的接口都占16个字节,你也可以使用其他接口来尝试。为什么只占16个字节呢?我们来看看接口是怎么实现的。
根据结构体内存对齐的规则,接口占8+8=16
个字节。
以a
为例
在内存中:
当然,接口的具体实现更为复杂,这里进行了简化帮助更好地理解。
接口是可比较的,要求实现该接口的类型不能是不可比较的类型(切片,map, 函数类型)。两个结构体是相等的,要求接口的动态类型(类型指针),和动态值(值指针)都相等。
- 接口与
nil
进行比较
输出
为什么不是true
呢? i
的值就是nil呀。接口与nil
进行比较,要求接口的动态类型和动态值都是nil,但i
的动态类型是*int
, 所以不相等。
- 接口与接口进行比较
输出
i1
和i2
动态类型不相等,所以i1 != i2
只有两个接口的动态类型和动态值都相等,接口才相等。