# Go语言接口 [课件](https://gitee.com/infraboard/go-course/blob/master/zh-cn/base/interface.md) + 解耦(Decoupling):调用者不需要知道具体类型,只需要知道接口 + 多态(Polymorphism):不同类型可以有相同的接口,统一处理 + 扩展性(Extensibility):新增类型时,不需要修改已有代码 ## 面向接口 ```go package main import "fmt" func main() { // dog := Dog{Name: "旺财"} fmt.Println(dog.Speak()) // cat := Cat{Name: "招财猫"} fmt.Println(cat.Speak()) // cow := Cow{Name: "小牛"} fmt.Println(cow.Speak()) // 必须知道对象的对象, 才能调用, 面向具体类型来编写代码, 依赖具体类型, 耦合度高 // 没有一层统一抽象,上层业务逻辑,需要知道对象,才能调用,非常麻烦,高耦合 // speakers := []interface{}{dog, cat, cow} // for _, speaker := range speakers { // switch speaker.(type) { // case Dog: // fmt.Println(speaker.(Dog).Speak()) // case Cat: // fmt.Println(speaker.(Cat).Speak()) // case Cow: // fmt.Println(speaker.(Cow).Speak()) // } // //... // } // 管理员,组织这些演技者,进行演讲 // interface 先制定规范, 底层系统按照规范进行实现,上层业务代码的编写将会是透明的,简单高效 // 这里的Speaker 和 Dog Cat Cow 都是type 他们是一种东西吗? // speakers = []Dog{}{dog1,dog2, dog3} // Speaker 是一种约束, 约束放入这个slice里面的对象,必须实现这个接口的所有方法 speakers := []Speaker{dog, cat, cow} for _, speaker := range speakers { fmt.Println(speaker.Speak()) } // 只关注 方法(接口), 不关注 对象的编程的方式,就是面向接口 } // 任何一个结构体 实现了这个接口的所有方法, 就实现了这个接口 // 接口是一层抽象, 只要实现了这个接口的所有方法, 就可以被当做这个接口来使用,屏蔽了底层系统 type Speaker interface { Speak() string // 说话方法 GetName() string // 获取名字方法 } // 2. 定义不同的类型 type Dog struct { Name string } // 3. 实现接口方法 func (d Dog) Speak() string { return "汪汪汪" } func (d Dog) GetName() string { return d.Name } type Cat struct { Name string } func (c Cat) Speak() string { return "喵喵喵" } func (c Cat) GetName() string { return c.Name } type Cow struct { Name string } func (c Cow) Speak() string { return "哞哞哞" } func (c Cow) GetName() string { return c.Name } ``` + 解耦: 调用者不需要知道具体类型,只需要知道接口, fmt.Println(speaker.Speak()) + 多态(Polymorphism):不同类型可以有相同的接口,统一处理, []Speaker{dog, cat, cow} + 扩展性(Extensibility):新增类型时,不需要修改已有代码 + Go语言的接口实现是隐式的, 底层系统按照规范进行实现,上层业务代码的编写将会是透明的,简单高效 ## 面向接口 ```go type Reader interface { Read(p []byte) (n int, err error) } // Writer is the interface that wraps the basic Write method. // // Write writes len(p) bytes from p to the underlying data stream. // It returns the number of bytes written from p (0 <= n <= len(p)) // and any error encountered that caused the write to stop early. // Write must return a non-nil error if it returns n < len(p). // Write must not modify the slice data, even temporarily. // // Implementations must not retain p. type Writer interface { Write(p []byte) (n int, err error) } // Closer is the interface that wraps the basic Close method. // // The behavior of Close after the first call is undefined. // Specific implementations may document their own behavior. type Closer interface { Close() error } // Seeker is the interface that wraps the basic Seek method. // // Seek sets the offset for the next Read or Write to offset, // interpreted according to whence: // [SeekStart] means relative to the start of the file, // [SeekCurrent] means relative to the current offset, and // [SeekEnd] means relative to the end // (for example, offset = -2 specifies the penultimate byte of the file). // Seek returns the new offset relative to the start of the // file or an error, if any. // // Seeking to an offset before the start of the file is an error. // Seeking to any positive offset may be allowed, but if the new offset exceeds // the size of the underlying object the behavior of subsequent I/O operations // is implementation-dependent. type Seeker interface { Seek(offset int64, whence int) (int64, error) } // ReadWriter is the interface that groups the basic Read and Write methods. type ReadWriter interface { Reader Writer } // ReadCloser is the interface that groups the basic Read and Close methods. type ReadCloser interface { Reader Closer } // WriteCloser is the interface that groups the basic Write and Close methods. type WriteCloser interface { Writer Closer } // ReadWriteCloser is the interface that groups the basic Read, Write and Close methods. type ReadWriteCloser interface { Reader Writer Closer } // ReadSeeker is the interface that groups the basic Read and Seek methods. type ReadSeeker interface { Reader Seeker } // ReadSeekCloser is the interface that groups the basic Read, Seek and Close // methods. type ReadSeekCloser interface { Reader Seeker Closer } // WriteSeeker is the interface that groups the basic Write and Seek methods. type WriteSeeker interface { Writer Seeker } // ReadWriteSeeker is the interface that groups the basic Read, Write and Seek methods. type ReadWriteSeeker interface { Reader Writer Seeker } ``` Io Reader和Writer接口 ```go // Reader is the interface that wraps the basic Read method. // // Read reads up to len(p) bytes into p. It returns the number of bytes // read (0 <= n <= len(p)) and any error encountered. Even if Read // returns n < len(p), it may use all of p as scratch space during the call. // If some data is available but not len(p) bytes, Read conventionally // returns what is available instead of waiting for more. // // When Read encounters an error or end-of-file condition after // successfully reading n > 0 bytes, it returns the number of // bytes read. It may return the (non-nil) error from the same call // or return the error (and n == 0) from a subsequent call. // An instance of this general case is that a Reader returning // a non-zero number of bytes at the end of the input stream may // return either err == EOF or err == nil. The next Read should // return 0, EOF. // // Callers should always process the n > 0 bytes returned before // considering the error err. Doing so correctly handles I/O errors // that happen after reading some bytes and also both of the // allowed EOF behaviors. // // If len(p) == 0, Read should always return n == 0. It may return a // non-nil error if some error condition is known, such as EOF. // // Implementations of Read are discouraged from returning a // zero byte count with a nil error, except when len(p) == 0. // Callers should treat a return of 0 and nil as indicating that // nothing happened; in particular it does not indicate EOF. // // Implementations must not retain p. type Reader interface { Read(p []byte) (n int, err error) } // Writer is the interface that wraps the basic Write method. // // Write writes len(p) bytes from p to the underlying data stream. // It returns the number of bytes written from p (0 <= n <= len(p)) // and any error encountered that caused the write to stop early. // Write must return a non-nil error if it returns n < len(p). // Write must not modify the slice data, even temporarily. // // Implementations must not retain p. type Writer interface { Write(p []byte) (n int, err error) } ``` 如何实现一个buf ```go func NewBuffer() *Buffer { return &Buffer{ // 固定 1k 大小的缓冲区 buf: make([]byte, 1024), dataLen: 0, } } // 实现 Reader和 Writer方法 type Buffer struct { buf []byte // 固定大小的缓冲区 dataLen int // 当前缓冲区中的数据量 } func (b *Buffer) Read(p []byte) (n int, err error) { if b.dataLen == 0 { return 0, io.EOF } // 读取缓冲区中的数据 n = copy(p, b.buf[:b.dataLen]) fmt.Println("read: ", n) // 移除已读数据(将未读数据前移) copy(b.buf, b.buf[n:b.dataLen]) b.dataLen -= n return n, nil } func (b *Buffer) Write(p []byte) (n int, err error) { // 计算剩余空间 available := len(b.buf) - b.dataLen if available == 0 { // 缓冲区已满 return 0, io.ErrShortBuffer } // 只写入缓冲区能容纳的数据(固定大小,不扩展) n = copy(b.buf[b.dataLen:], p) b.dataLen += n fmt.Printf("write: %d 字节, 缓冲区使用: %d/%d\n", n, b.dataLen, len(b.buf)) // 如果没能写入全部数据,返回 ErrShortBuffer if n < len(p) { return n, io.ErrShortBuffer } return n, nil } func (b *Buffer) String() string { return string(b.buf[:b.dataLen]) } // Reset 清空缓冲区 func (b *Buffer) Reset() { b.dataLen = 0 } ```