interface {} 可以用于模拟多态
xdm 咱们写一个简单的例子,就举动物的例子
写一个 Animal 的接口,类似于 java 里面的抽象类 ,Animal 的接口 中有 2 个方案待实现
写一个 Cat 来继承 Animal , 实现 Eat 方法和 Drink 方法
- 动物都有吃和喝的行为,小猫吃的行为是吃鱼,小猫的喝的行为是喝可乐
- 最后在主函数中,使用父类的指针,来指向子类的实例化的一个子类地址
&Cat{}var a Animal
这里需要注意,Animal 本身是 接口类型,自身就是一个指针
运行上述代码查看效果
# go run main.go
i like
abandon
没有毛病,小猫眯爱吃鱼,不爱喝水
interface{} 需要注意空和非空的情况
什么叫做空的 interface{} , 什么又叫做非空的 interface{} 呢?
testInterface 函数
可以猜猜看,上面这个小案例会输出什么结果
testInterfacetest is nil
执行上述代码后,查看结果
# go run main.go
test is not nil
看到上面的结果,是不是觉得很奇怪,和自己的预期不一致
没关系,之前的文章我们说到过,觉得一个技术点奇怪,不是我们所期望的效果,原因是我们对其原理不够了解,不够熟悉
现在先来回答一下上面的问题
空接口:意思是没有方法的接口,interface{} 源码中表示为 eface 结构体
非空接口:表示有包含方法的接口 , interface{} 源码中表示为 iface 结构体
暂时先来直接介绍源码中的结构体
iface结构体,非空
tab
指的是具体的类型信息,是一个 itab 结构,结构中成员如上,这里面包含的都是借口的关键信息,例如 hash 值 ,函数指针,等等,后续详细剖析 interface{} 原理的时候再统一说
data
具体的数据信息
eface结构体
_type
类型信息,和上面的 非空接口类似 , 这个_type 类型决定下面的 data 字段如何去解释数据
data
具体的数据信息
看到这里,细心的 xdm 是不是就可以看出来,我们上面写的 Animal 接口,其实是一个非空接口,因为里面有包含方法,所以他的底层是一个 iface 结构体 ,非空接口
test is not nil
这里顺带说一下,golang 中,还有哪些数据结构是和 nil 比较是否为零值,这个点我们也可以看看源码
源码中有说到,可以对 指针,通道,函数,接口,map,切片类型使用 nil
好了,本次就到这里,知识点要用起来才有价值