接口

接口

  • 接口声明

  • 接口初始化

    • 单纯的声明一个接口变量没有任何意义,接口只有被初始化为具体的类型时才有意义,

    • 接口作为一个抽象层,起到抽象和适配的作用。没有初始化的接口变量,其默认值时 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 语句达到同样的效果

原文地址:https://www.cnblogs.com/jcjc/p/12500694.html