Golang中接口的作用:
1. 可以作为函数和方法的参数或者返回值的使用,可以通过类型断言和switch方法
2.多态的使用,在程序设计中,抽象出某些对象共同拥有的方法,多种类型实现同一接口,通过接口变量指向具体对象操作这些方法。
Golang接口的使用
interface 是方法或行为声明的集合,其中所有的方法都没有方法体,接口中也不能有其他变量
interface接口方式实现比较隐性,任何类型的对象必须实现interface所包含的全部方法,则表明该类型实现了该接口。
interface还可以作为一中通用的类型,其他类型变量可以给interface声明的变量赋值。
interface 可以作为一种数据类型,实现了该接口的任何对象都可以给对应的接口类型变量赋值。
一个自定义的类型可以实现多个接口,可以理解为多继承可以使用多个方法,一个接口(比如A接口)可以继承多个别的接口(比如B,C接口),这时如果要实现A接口,也必须将B,C接口的方法也全部实现
具体使用
一个接口本身不能创建实例,但是可以指向一个实现该接口的自定义类型的实例,自定义类型既可以是函数也可以是结构体,如果自定义的类型没有实现接口,就不可以将结构体赋给接口
自定义类型为结构体
自定义类型为函数
指向接口的指针
如果希望接口方法修改基础数据,则必须使用指针传递(将对象指针赋值给接口变量)。
接口的合理性验证
- 将实现特定接口的导出类型作为接口API 的一部分进行检查
- 实现同一接口的(导出和非导出)类型属于实现类型的集合
- 任何违反接口合理性检查的场景,都会终止编译, 并通知给用户
错误使用接口会在编译期报错. 所以可以利用这个机制让部分问题在编译期暴露。在实际的项目中可能会导致代码冗余。
这段代码在编译时不会报错,但是运行时会报错(var _ temp = Son{}可以帮助我们在编译时发现错误),Son没有实现eat方法,如果去掉Father的注释可以正常运行,而且可以调用f方法
*Handlernil
Good代码
接收器 (receiver) 与接口,接口与具体方法集的匹配
一个类型可以有值接收器方法集和指针接收器方法集
使用值接收器的方法既可以通过值调用,也可以通过指针调用。带指针接收器的方法只能通过指针或 addressable values调用(其实和值调用类似)。
如果方法的接收者是值类型,无论调用者是对象还是对象指针,修改的都是对象的副本,不影响调用者;如果方法的接收者是指针类型,则调用者修改的是指针指向的对象本身。
通常我们使用指针作为方法的接收者的理由:
- 使用指针方法能够修改接收者指向的值。
- 可以避免在每次调用方法时复制该值,在值的类型为大型结构体时,这样做会更加高效。
map中的值是无法取地址的,因为它不是一个变量。这里的值对象仅仅指一些拿不到地址的情况。
这种情况编译是可以通过的,这就是通过addressable values调用的
接口的匹配
- 值方法集和接口匹配
- 给接口变量赋值的不管是值还是指针对象,都ok,因为都包含值方法集
- 指针方法集和接口匹配
- 只能将指针对象赋值给接口变量,因为只有指针方法集和接口匹配
- 如果将值对象赋值给接口变量,会在编译期报错(会触发接口合理性检查机制)
关于interface关键字
interface有两种表现形式,空接口eface、非空接口iface
其底层都是由不同的struct表示
eface底层结构
它就是代码中经常用到的interface{},
Case 1 :
interface{}内部除了指针还有类型,当做图中的赋值,它还携带着类型就不再是nil了
Case 2:
因为interface{}本身就可以接收任意类型的参数,而*interface{}只能接收*interface{}的参数
iface就是带有方法声明的接口,其底层结构
Case 1:
在赋值的时候就以及带着结构体的各种类型信息了