【Go笔记】接口与设计模式
接口的特征
- 隐藏细节
- 控制系统复杂性
- 权限控制
- 接口必须实现所有的方法
接口的使用
- 隐形声明 - 即只要实现接口内的所有方法,则实现了该接口
- 接口本身可以作为一个父类使用,即可以接受所有实现了该接口的数据类型,然后调用接口内定义了的方法
- 一个类型可以同时实现多个接口
- 鼓励使用组合而不是继承的方式来实现OOP
- 使用
s, ok := i.(Type)
断言来获取结构内存储的类型与数据 - 使用
switch e.(Type)
来断言空接口中的数据类型 - 接口之间可以比较
接口的底层原理
- 首先将类型的方法与接口的签名方法按照相同的方法排序,然后再来一一对应判断是否实现
- 因为接口的结构体中的数据部分是一个指向内存数据的地址,所以当栈上的数据被分配到接口的时候,必然会在堆中开辟一个新的内存空间来存储,从而内存逃逸
- 接口的调用成本比函数要大,但是依然可以忽略不计,且设计者鼓励开发者使用接口
- 接口的调用开销主要是函数的寻址过程,其中涉及到CPU的分支预测导致的性能损耗。不过就算有性能损耗,不仅损耗极小,而且现代CPU都有缓存,常用接口及其对应函数已经被保存到L1缓存中供快速查询
- 两个接口之间也可以转换,前提是来源接口的签名方法必须可以覆盖目标接口的签名方法
- 空接口可以承载任何数据类型,但是有内存逃逸、eface创建、堆gc等性能损耗,相比接口要高不少,因此在某些高性能场景中需要被考虑到
- 接口的仨陷阱
-
- 当接口中存储的是值,结构体是指针的时候,动态调用无法通过编译
-
- 将类型切片转换为接口切片时无法通过编译 - 因为批量转换接口是效率非常低的操作
-
- 接口值为
nil
的时候,接口本身不为nil
,比如
- 接口值为
1 |
|
总结
- 接口的Go中的地位很重要,所有大规模程序设计都需要设计接口
- 相比直接调用函数,接口会有内存逃逸,创建接口对象,gc等性能消耗,但是总体而言接口赋值次数很少,其性能损耗可以忽略不计
- 接口决定了Go语言面向组合的程序设计模式,是与其他编程语言最显著的差别
- 尽量以更少的方法签名来定义接口,通过组合的方式构造更加具体的结构
【Go笔记】接口与设计模式
https://study.0x535a.cn/go-note/go-interface-pattern/