Go 关于interface的理解(一)

Go 中的 interface 是一种抽象类型。一个 interface 就是包含了一系列行为的method集合。 关于 interface 的定义,以 Writer 为例:安全

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

Go 中的 interface 属于隐式接口。一个类型若是拥有一个接口须要的全部方法,那么这个类型就实现了这个接口。函数


在标准库 fmt 包中的一系列方法能够很好地诠释 interface 是如何应用到实践当中的。指针

package fmt

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()
}

Fprintf 的前缀 F 表示文件(File)也代表格式化输出结果应该被写入第一个参数提供的文件中。
在Printf函数中的第一个参数os.Stdout是*os.File类型;
在sprintf函数中的第一个参数&buf是一个指针,指向能够写入字节的内存缓冲区;
而Fprintf函数中的第一个参数是一个 interface 类型 io.Writer。io.Writer 定义了函数 Fprintf 和这个函数调用者之间的约定,该约定保证了 Fprintf 接受任何知足 io.Writer 接口的值。
由于 fmt.Fprintf 函数没有对具体操做的值作任何假设而是进京经过 io.Writer 接口的约定来保证行为,因此第一个参数能够安全地传入任何一个具体类型的值,只须要它能知足 io.Writer 接口。
一个类型能够自由的使用另外一个知足相同接口的类型来进行替换被称做可替换性(LSP里氏替换)。这是一个面向对象的特征。code


定义 interface
以标准库中的 io 包为例, io 包中定义了不少有用的 interface :orm

package io

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

type Writer interface {
    Write(p []byte) (n int, err error)
}

type Closer interface {
    Close() error
}
/* Reader 表明任何能够去读 byte 的类型, Writer 表明任何能够写入 byte 的类型, Closer 表明任何能够执行 close 的类型 */

除此以外,还能在 io 包中发现其余组合式的 interface:对象

package io

type ReaderWriter interface {
    Reader
    Writer
}

type ReadWriteCloser interface {
    Reader
    Writer
    Closer
}
/*该语法和结构体内嵌类似,能够用这种方式简写命名一个接口,称为接口内嵌*/

实现接口的条件
一个类型若是拥有一个接口须要的全部方法,那么这个类型就实现了这个接口。
接口指定的规则也很是简单:表达一个类型属于某个接口只要这个类型实现这个接口,因此:接口

var w io.Writer
w = os.Stdout          //OK: *os.File has Write method
w = new(bytes.Buffer)  //OK: *bytes.Buffer has write method
w = time.Second        //compile error: time.Duration lacks Write method

var rwc io.ReadWriteCloser
rwc = os.Stdout        //OK: *os.File has Read, Write, Close methods
rwc = new(bytes.Buffer)//compile error: *bytes.Buffer lacks Close method

/* 这个规则甚至适用于等式右边自己也是一个接口类型 */
w = rwc         // OK: io.ReadWriteCloser has Write method
rwc = w         // compile error: io.Writer lacks Close method