# 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
}
```