zoukankan      html  css  js  c++  java
  • go基础6-接口1

    接口

    接口类型是对于其他类型行为的抽象;因为接口类型通过只声明不定义具体实现细节,来增加函数的灵活性和扩展性;
    go中接口类型可以进行隐式实现,即具体实现中不需要定义所有接口声明的函数,只需要按需使用即可.这种定义方式可以让你修改接口时,不用改变已有实现;

    接口约定

    通过接口约定可以增加函数的灵活性.你不用每次都定义具体的结构和操作集,只通过方法定义即可明确可以通过它实现的功能.不定义具体结构,只是接口的约定的方式可以灵活的实现里氏替换;

    func Fprintf(w io.Writer, format string, args ...interface{}) (int, error)
    func Printf(format string, args ...interface{}) (int, error) {
        return Fprintf(os.Stdout, format, args...)
    }
    func Sprintf(format string, args ...interface{}) string {
        var buf bytes.Buffer
        Fprintf(&buf, format, args...)
        return buf.String()
    }
    
    // Writer接口定义
    package io
    type Writer interface {
        Write(p []byte) (n int, err error)
    }
    

    因为os.Stdout和&buf满足Writer接口约定,所以可以使用Fprintf函数.

    接口类型

    接口类型定义了具体的方法集合,而实现方法的具体类型是这个接口类型的实例;

    package io
    type Reader interface {
        Read(p []byte) (n int, err error)
    }
    

    接口还可以通过组合方式进行扩展

    type ReadWriter interface {
        Reader
        Writer
    }
    

    接口实现

    实现:一个类型拥有一个接口所有的方法.这意味着:表达一个类型属于某个接口只要实现该接口即可.

    var w io.Writer
    w = os.Stdout 
    

    如果具体类型T,它的方法接收器的类型可以是T或*T的指针.在T上调用*T是合法的,因为编译器隐式的获取了它的地址.但这仅仅是一个语法糖,T类型不拥有*T指针的方法.

    接口可以封装和隐藏具体实现类型及其值,只有接口中暴露的方法可以被调用到:

    os.Stdout.Close() // OK: *os.File has Close method
    
    var w io.Writer
    w = os.Stdout
    w.Close()  // compile error: io.Writer lacks Close method
    

    空接口类型:interface{}.空接口类型没有实现类型要求,它可以接收任意值,也因此不能直接对它持有值做操作.

    go的接口不需要显示定义,在你需要的时候定义一个新的抽象或特定特点的组,而不需要修改具体类型的定义.因为你只要包含该接口的所有方法即意味着实现该接口,所以接口通过隐式实现很灵活.

    接口值

    接口值:包含了类型和值两部分.它们被称为接口的动态类型和动态值.类型部分代表与之相关类型的描述符.类型描述符指类型的名称和方法.因为go是静态类型语言,类型是编译器的概念,所以一个类型不是一个值.

    1 var w io.Writer
    2 w = os.Stdout
    3 w = new(bytes.Buffer)
    4 w = nil
    

    1 定义w变量并初始化.它会会获取接口的零值,type和value都是nil
    接口零值

    2 将os.File类型的值赋给变量w.赋值过程会进行具体类型到接口类型的隐式转换.它的动态类型被设为os.File指针的类型描述符,它的动态值持有os.Stdout的拷贝;
    os.Stdout
    因为编译期,我们不知道接口值的动态类型是什么,所以一个接口上的调用必须使用动态分配.实际赋值等价于os.Stdout.Write([]byte("hello")) // "hello"

    3 将*bytes.Buffer赋值给变量w.
    bytes.Buffer

    4 将nil赋值给w.又回到初始化状态.

    一个接口值可以持有任意大的动态值.从概念上,不论接口值多大,动态值总能容下它.
    接口值可进行==和!=比较.但是由于接口值类型是任意的,如果接口值的动态类型都是不可比较的类型(如切片),比较时会产生panic.
    所以进行值比较时,你必须要确定类型可比较,你可以通过fmt.Printf("%T ", w)来查看具体类型.

    nil接口值与nil指针接口值:接口值变量初始化值为nil,但是nil指针接口值初始化值不是nil而是类型是变量的指针类型,它的值为nil.这一点常会造成误判,引起程序bug.
    nil指针接口值

  • 相关阅读:
    Altium Designer如何导出SMT贴片机用的坐标文件
    STM8S003设计注意事项
    Keil4打开KEIL5未响应卡死的问题
    STM32 adc 多通道采集相互串扰问题解决
    STM32 RS485 和串口 只能接收不能发送问题解决
    AD中元器件报警的处理——器件高度报警
    QT乱码解决办法《转》
    STM32下载失败,st-link v2 在线下载sw模式检测不到
    docker部署普罗米修斯监控
    进程管理常用命令
  • 原文地址:https://www.cnblogs.com/chengmuyu/p/13585720.html
Copyright © 2011-2022 走看看