接口组合 #

一、接口组合概述 #

Go通过接口嵌入实现组合,将多个小接口组合成大接口。

二、接口嵌入 #

2.1 基本语法 #

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

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

type ReadWriter interface {
    Reader  // 嵌入Reader
    Writer  // 嵌入Writer
}

2.2 等价定义 #

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

2.3 使用示例 #

go
type File struct{}

func (f File) Read(p []byte) (n int, err error) {
    return 0, nil
}

func (f File) Write(p []byte) (n int, err error) {
    return 0, nil
}

var rw ReadWriter = File{}

三、标准库组合 #

3.1 io包接口 #

go
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
}

type Seeker interface {
    Seek(offset int64, whence int) (int64, error)
}

3.2 组合接口 #

go
type ReadWriter interface {
    Reader
    Writer
}

type ReadCloser interface {
    Reader
    Closer
}

type WriteCloser interface {
    Writer
    Closer
}

type ReadWriteCloser interface {
    Reader
    Writer
    Closer
}

type ReadSeeker interface {
    Reader
    Seeker
}

type WriteSeeker interface {
    Writer
    Seeker
}

type ReadWriteSeeker interface {
    Reader
    Writer
    Seeker
}

四、组合的好处 #

4.1 灵活性 #

go
func processReader(r Reader) {
    // 只需要Read方法
}

func processWriter(w Writer) {
    // 只需要Write方法
}

func processReadWriter(rw ReadWriter) {
    // 需要Read和Write方法
}

4.2 可组合性 #

go
func Copy(dst Writer, src Reader) (written int64, err error) {
    buf := make([]byte, 32*1024)
    for {
        nr, er := src.Read(buf)
        if nr > 0 {
            nw, ew := dst.Write(buf[0:nr])
            if nw > 0 {
                written += int64(nw)
            }
            if ew != nil {
                err = ew
                break
            }
        }
        if er != nil {
            err = er
            break
        }
    }
    return
}

4.3 解耦 #

go
type Storage interface {
    Save(key string, data []byte) error
    Load(key string) ([]byte, error)
}

type Cache interface {
    Get(key string) ([]byte, bool)
    Set(key string, data []byte)
}

type CachedStorage interface {
    Storage
    Cache
}

五、接口层次 #

5.1 基础接口 #

go
type Sizer interface {
    Size() int64
}

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

5.2 组合接口 #

go
type SizedReader interface {
    Reader
    Sizer
}

5.3 扩展接口 #

go
type AdvancedReader interface {
    SizedReader
    ReadAt(p []byte, off int64) (n int, err error)
}

六、实际应用 #

6.1 数据库接口 #

go
type Queryer interface {
    Query(query string, args ...interface{}) (*Rows, error)
}

type Execer interface {
    Exec(query string, args ...interface{}) (Result, error)
}

type QueryExecer interface {
    Queryer
    Execer
}

type Preparer interface {
    Prepare(query string) (*Stmt, error)
}

type DB interface {
    QueryExecer
    Preparer
    Begin() (*Tx, error)
    Close() error
}

6.2 HTTP接口 #

go
type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

type HandlerFunc func(ResponseWriter, *Request)

func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    f(w, r)
}

type Middleware func(Handler) Handler

6.3 日志接口 #

go
type Logger interface {
    Log(msg string)
}

type LeveledLogger interface {
    Logger
    Debug(msg string)
    Info(msg string)
    Warn(msg string)
    Error(msg string)
}

type FormattedLogger interface {
    LeveledLogger
    Printf(format string, args ...interface{})
}

七、接口与结构体组合 #

7.1 结构体嵌入接口 #

go
type Handler struct {
    http.Handler
}

func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Println("Before")
    h.Handler.ServeHTTP(w, r)
    fmt.Println("After")
}

7.2 装饰器模式 #

go
type LoggingHandler struct {
    handler http.Handler
    logger  Logger
}

func (h *LoggingHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    h.logger.Log(r.URL.Path)
    h.handler.ServeHTTP(w, r)
}

func WithLogging(h http.Handler, l Logger) http.Handler {
    return &LoggingHandler{handler: h, logger: l}
}

八、组合模式 #

8.1 适配器模式 #

go
type LegacyReader interface {
    ReadOld() []byte
}

type ReaderAdapter struct {
    legacy LegacyReader
}

func (a ReaderAdapter) Read(p []byte) (n int, err error) {
    data := a.legacy.ReadOld()
    copy(p, data)
    return len(data), nil
}

8.2 策略模式 #

go
type SortStrategy interface {
    Sort([]int)
}

type QuickSort struct{}

func (s QuickSort) Sort(arr []int) {
    // 快速排序实现
}

type MergeSort struct{}

func (s MergeSort) Sort(arr []int) {
    // 归并排序实现
}

type Sorter struct {
    strategy SortStrategy
}

func (s *Sorter) SetStrategy(strategy SortStrategy) {
    s.strategy = strategy
}

func (s *Sorter) Sort(arr []int) {
    s.strategy.Sort(arr)
}

九、最佳实践 #

9.1 小接口优先 #

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

// 避免
type BigInterface interface {
    Read(p []byte) (n int, err error)
    Write(p []byte) (n int, err error)
    Close() error
    Flush() error
}

9.2 组合而非继承 #

go
// 好:组合
type ReadWriter interface {
    Reader
    Writer
}

// 避免:大接口
type ReadWriter interface {
    Read(p []byte) (n int, err error)
    Write(p []byte) (n int, err error)
    // 更多方法...
}

9.3 接口隔离 #

go
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
}

// 按需组合
type ReadCloser interface {
    Reader
    Closer
}

十、总结 #

接口组合要点:

特性 说明
嵌入 接口嵌入接口
组合 组合多个小接口
灵活性 按需组合接口
解耦 降低耦合度

关键点:

  1. 接口嵌入:将小接口组合成大接口
  2. 标准库:io包大量使用接口组合
  3. 灵活性:按需组合,灵活使用
  4. 小接口:接口越小越灵活
  5. 解耦:组合降低耦合度

准备好学习空接口了吗?让我们进入下一章!

最后更新:2026-03-26