• GO_08:GO语言基础之interface


    接口interface

      1. 接口是一个或多个方法签名的集合

      2. 只要某个类型拥有该接口的所有方法签名,即算实现该接口,无需显示声明实现了哪个接口,这称为 Structural typing

      3. 接口只有方法声明,没有实现,没有数据字段

      4. 接口可以匿名嵌入其它接口,或切入到结构中去

      5. 将对象赋值给接口时,会发生拷贝,而接口内部存储的是指向这个复制品到指针,既无法修改复制品的状态,也无法获取指针

      6. 只有当接口存储的类型和对象都为 nil 时,接口才等于 nil

      7. 接口调用不会做 receiver 的自动转换

      8. 接口同样支持匿名字段方法

      9. 接口也可实现类似 OOP 中的多态

      10. 空接口可以作为任何类型数据的容器

    那么,让我们先来看一个简单的接口应用案例:

    package main
    
    import "fmt"
    
    /**
    定义接口
     */
    type USB interface {
        Name() string    // 定义了名为Name的方法且返回类型为String
        Connect()    // 定义了名为Connect的方法,没有返回类型形如java中的void
    }
    
    /**
    使用结构体(java中的class) 来实现接口中的方法
    具体如何实现是通过为定义的结构体绑定方法来实现,故可以看到下面代码开始先定义一个结构体之后再为这个结构添加方法
     */
    type PhoneConnecter struct {
        // 定义内部变量
        name string
    }
    
    func (phone PhoneConnecter) Name() string {
        return phone.name
    }
    
    func (phone PhoneConnecter) Connect() {
        fmt.Println("Connect:", phone.name)
    }
    
    func main() {
        /*var a USB
        a = PhoneConnecter{"PhoneConnecter"}*/
        //以上注释代码可以简写为以下形式
        a := PhoneConnecter{"PhoneConnecter"}
        a.Connect()
        //那么有人问来,那你怎么知道 a 是实现来 USB 接口呢?那么我们再定义一个Disconnect函数,参数就传入 USB 类型
        Disconnect(a)
        /**
        从结果可以看出实现接口并没有声明实现哪个接口
         */
    }
    
    func Disconnect(usb USB) {
        fmt.Println("Disconnected.")
    }

    运行结果:

    Connect: PhoneConnecter
    Disconnected.
    

    类型断言

      1. 通过类型断言的 ok pattern可以判断接口中的数据类型

      2. 使用 type switch 则可以针对空接口进行比较全面的类型判断

    接口转换

      可以将拥有超集的接口转换为子集的接口

    更加深入的示例:

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 /**
     8 定义接口
     9  */
    10 type USB interface {
    11     Name() string    // 定义了名为Name的方法且返回类型为String
    12     Connecter      // 接口嵌套,USB 接口也就拥有了 Connecter 接口中 Connect() 方法
    13 }
    14 
    15 type Connecter interface {
    16     Connect()
    17 }
    18 
    19 /**
    20 定义结构体
    21  */
    22 type PhoneConnecter struct {
    23     // 定义内部变量
    24     name string
    25 }
    26 
    27 /**
    28 真对结构体绑定的方法method
    29  */
    30 func (phone PhoneConnecter) Name() string {
    31     return phone.name
    32 }
    33 
    34 func (phone PhoneConnecter) Connect() {
    35     fmt.Println("Connect:", phone.name)
    36 }
    37 
    38 func main() {
    39     a := PhoneConnecter{"PhoneConnecter"}
    40     a.Connect()
    41     Disconnect(a)
    42     DisconnectAll(a)
    43     DisconnectSwitch(a)
    44 
    45     // 演示接口类型转换
    46     phone := PhoneConnecter{"PhoneConnecter"} // 声明 PhoneConnecter,其实它是实现来 USB 接口的
    47     var b Connecter                  // 声明 Connecter 接口
    48     b = Connecter(phone)             // 将 USB接口的类型强制转换为 Connecter 类型。即Go语言中接口转换只能从高——>低
    49     b.Connect()                    // 当前只能调用 Connect 方法并没有 Name 方法了,因为它已经是 Connecter 类型了,不存在 Name 方法
    50 }
    51 
    52 func Disconnect(usb USB) {
    53     /**
    54     这里是通过类型断言来判定当前是哪个对象调用并打印
    55     类型断言格式:usb.(要判断的对象),判断传入的是否为PhoneConnecter类型
    56      */
    57     if phone, ok := usb.(PhoneConnecter); ok {
    58         fmt.Println("Disconnected:", phone.name)
    59         return
    60     }
    61     fmt.Println("Unknown decive.")
    62 }
    63 
    64 /**
    65 Go语言中类型定义只要符合定义的接口那么它就实现来该接口,在java语言中都有一个顶级父类叫 Object。那么在Go语言中有吗?
    66 当然有的,通过接口概念可以了解到当我们定义一个空接口的时候,任何类型都会继承它。那么针对Disconnect方法我们就可以定义一种更加广泛的应用方式
    67  */
    68 func DisconnectAll(usb interface{}) {
    69     if phone, ok := usb.(PhoneConnecter); ok {
    70         fmt.Println("DisconnectAll:", phone.name)
    71         return
    72     }
    73     fmt.Println("Unknown decive.")
    74 }
    75 
    76 /**
    77 在Go语言中可以用另外一种方式进行断言,叫:type switch
    78  */
    79 func DisconnectSwitch(usb interface{}) {
    80     switch v := usb.(type) {
    81     case PhoneConnecter:
    82         fmt.Println("DisconnectSwitch:", v.name)
    83     default:
    84         fmt.Println("Unknown decive.")
    85     }
    86 }

    运行结果:

    Connect: PhoneConnecter
    Disconnected: PhoneConnecter
    DisconnectAll: PhoneConnecter
    DisconnectSwitch: PhoneConnecter
    Connect: PhoneConnecter
    
  • 相关阅读:
    线程安全-一个VC下多个网络请求
    [从头学数学] 第172节 直线与方程
    ASP.NET MVC 视图(一)
    Pixhawk之姿态解算篇(1)_入门篇(DCM Nomalize)
    Android基础新手教程——3.7 AnsyncTask异步任务
    IC卡、ID卡、M1卡、射频卡的区别是什么【转】
    .gitignore文件配置:keil工程文件类型【转】
    RK平台images打包细则【转】
    使用/dev/uinput的简要介绍(含demo程序)【转】
    Linux--struct file结构体【转】
  • 原文地址:https://www.cnblogs.com/liang1101/p/6616854.html
Copyright © 2020-2023  润新知