接口
-
接口声明
-
接口初始化
-
单纯的声明一个接口变量没有任何意义,接口只有被初始化为具体的类型时才有意义,
-
接口作为一个抽象层,起到抽象和适配的作用。没有初始化的接口变量,其默认值时 nil。
-
var i io.Reader fmt.Printf("%T ", i ) // <nil>
-
-
接口绑定具体类型的实例的过程称为接口初始化。接口变量支持两种直接初始化的方法
-
实例赋值接口
- 如果具体类型的实例的方法集是接口的方法集的超集,则称为具体类型实现了接口,可以将该具体类型的实例直接赋值给接口类型的变量,此时编译器会进行静态的类型检查,接口被初始化后,调用接口的方法就相当于调用接口绑定的具体类型的方法,这就是接口调用的语义。
-
接口变量赋值接口变量
- 已经初始化的接口类型变量 a 直接赋值给两一个接口变量 b,要求 b 的方法集是 a 的方法集的子集,此时 Go 编译器在编译时进行方法集静态检查,这个过程也是初始化的一种方式,此时接口变量 b 绑定的具体的实例时接口变量 a 半丁的具体实例的父副本。
-
接口方法的调用
-
接口方法的调用和普通方法的调用是有区别的,接口方法调用的最终地址实在运行期决定的,将具体类型方法变量赋值个接口后,会使用具体类型的方法指针初始化接口变量,当调用接口变量的方法时,实际上时简洁的调用实例的方法,接口方法调用不是一种直接的调用,有一定的运行时开销
-
直接调用未出初始化的接口变量的方法会发生panic
-
package main type Printer interface { Print() } type S struct { } func (s S) Print() { println("print") } func main(){ var i Printer // 没有初始化的接口调用期方法会产生 panic // panic: runtime error: invalid memory address or nil pointer dereference // i.Print() // 必须初始化 i = S{} i.Print() }
-
-
-
接口类型查询和类型断言
-
类型断言
-
语法形式 i.(TypeName) // i 必须时接口变量,如果时具体类型的变量,则编译器会报错,TypeName 可以是接口类型,也可以是具体类型名
-
-
类型判断(Type Switches)
-
// 接口类型查询的语法格式如下: switch V := i.(Type) case type1: xxx case type2: xxx default: xxx // 语义分析 // 接口查询有两层语义,以式查询一个接口变量底层绑定的底层变量的具体类型是什么,而是查询接口变量绑定的底层的变量是否还实现了其他接口 // 注意: i 必须是接口类型 具体类型实例是静态的,在类型声明后就不会在变化,所以具体类型的变量不存在类型查询,类型铲鲟是对一个接口变量进行操作,也就是说,上文中的 i 必须是 接口变量,如果 i 是未初始化的接口变量,则 v 的值是nil case 字句后面可以根非接口类型名,也可以是接口类型名,匹配时按照 case 字句的顺序进行的,
-
-
1、类型查询和类型断言具有相同的语义,只是语法格式不同,二者都能判断接口变量绑定的实例的具体类型,以及类型判断接口变量绑定的实例是否满足满足一个接口类型
-
2、类型查询使用case 字句一次判断多个类型,类型断言一次只能判断一个类型,档摊类型断言可以使用 if else if 语句达到同样的效果
-
-
-