Go语言中io.Reader和io.Writer的详解与实现

 更新时间:2016年09月01日 09:17:15   投稿:daisy  
在Go语言的实际编程中,几乎所有的数据结构都围绕接口展开,接口是Go语言中所有数据结构的核心。在使用Go语言的过程中,无论你是实现web应用程序,还是控制台输入输出,又或者是网络操作,不可避免的会遇到IO操作,使用到io.Reader和io.Writer接口。下面来详细看看。

一、前言

也许对这两个接口和相关的一些接口很熟悉了,但是你脑海里确很难形成一个对io接口的继承关系整天的概貌,原因在于godoc缺省并没有像javadoc一样显示官方库继承关系,这导致了我们对io接口的继承关系记忆不深,在使用的时候还经常需要翻文档加深记忆。

本文试图梳理清楚Go io接口的继承关系,提供一个io接口的全貌。

二、io接口回顾

首先我们回顾一下几个常用的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
}
type Seeker interface {
  Seek(offset int64, whence int) (int64, error)
}
type ReaderFrom interface {
  ReadFrom(r Reader) (n int64, err error)
}
type WriterTo interface {
  WriteTo(w Writer) (n int64, err error)
}
type ReaderAt interface {
  ReadAt(p []byte, off int64) (n int, err error)
}
type WriterAt interface {
  WriteAt(p []byte, off int64) (n int, err error)
}

以及

type ByteReader interface {
  ReadByte() (byte, error)
}
type ByteWriter interface {
  WriteByte(c byte) error
}

ByteScanner比ByteReader多了一个UnreadByte方法。

type ByteScanner interface {
  ByteReader
  UnreadByte() error
}
type RuneReader interface {
  ReadRune() (r rune, size int, err error)
}
type RuneScanner interface {
  RuneReader
  UnreadRune() error
}

组合接口

Go标准库还定义了一些由上面的单一职能的接口组合而成的接口。

type ReadCloser interface {
  Reader
  Closer
}
type ReadSeeker interface {
  Reader
  Seeker
}
type ReadWriter interface {
  Reader
  Writer
}
type ReadWriteCloser interface {
  Reader
  Writer
  Closer
}
type ReadWriteSeeker interface {
  Reader
  Writer
  Seeker
}
type WriteCloser interface {
  Writer
  Closer
}
type WriteSeeker interface {
  Writer
  Seeker
}

从它们的定义上可以看出,它们是最小粒度的组合。

最小接口的扩展

有些结构体struct实现并且扩展了接口,这些结构体是。

type LimitedReader struct {
  R Reader // underlying reader
  N int64 // max bytes remaining
}
type PipeReader struct {
  // contains filtered or unexported fields
}
type PipeWriter struct {
  // contains filtered or unexported fields
}
type SectionReader struct {
  // contains filtered or unexported fields
}

下面我会将它们的继承关系画出来。

一些辅助方法

一些辅助方法可以生成特殊类型的Reader或者Writer:

func LimitReader(r Reader, n int64) Reader
func MultiReader(readers ...Reader) Reader
func TeeReader(r Reader, w Writer) Reader
func MultiWriter(writers ...Writer) Writer

三、继承关系

当然,Go语言中并没有Java中那样的继承关系,而是基于duck type形式实现,我用下图尝试展示Go io接口的继承关系。

    其中黄色是 bufio 包下的类型,

    绿色是 archive.tar 包下的类型,

    蓝色是 bytes 包下的类型,

    粉红色是 strings包下的类型,

    紫色是 crypto.tls 包下的类型。

Rand是math.rand包下的类型。

File是os包下的内容。

`Rand`左边的那个Reader是image.jpeg下的内容。

我们最常用的是包io、bytes、bufio下的类型,所以这几个包下的类型要记牢,在第三库中经常会出现它们的身影。

上图中并没有把mime/multipart.File和 net/http.File列出来,主要是图太复杂了,它们实现的接口和os.File类似。

当然你可能会问,你怎么整理的它们的继承关系?事实上,你可以通过godoc -analysis=type -http=:6060生成带继承关系的Go doc,并且它还可以将你本地下载的库中的继承关系也显示出来。

四、总结

以上就是关于Go语言中io.Reader和io.Writer的详解与实现的全部内容,希望这篇文章的内容对大家的学习和工作能有所帮助,如果有疑问可以留言交流。

相关文章

  • 详解在Go语言单元测试中如何解决Redis存储依赖问题

    详解在Go语言单元测试中如何解决Redis存储依赖问题

    在编写单元测试时,除了 MySQL 这个外部存储依赖,Redis 应该是另一个最为常见的外部存储依赖了,本文就来讲解下如何解决 Redis 外部依赖,文章通过代码示例介绍的非常详细,需要的朋友可以参考下
    2023-08-08
  • go语言异常panic和恢复recover用法实例

    go语言异常panic和恢复recover用法实例

    这篇文章主要介绍了go语言异常panic和恢复recover用法,实例分析了异常panic和恢复recover使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-03-03
  • 详解Golang中NewTimer计时器的底层实现原理

    详解Golang中NewTimer计时器的底层实现原理

    本文将主要介绍一下Go语言中的NewTimer,首先展示基于NewTimer创建的定时器来实现超时控制。接着通过一系列问题的跟进,展示了NewTimer的底层实现原理,需要的可以参考一下
    2023-05-05
  • golang动态创建类的示例代码

    golang动态创建类的示例代码

    这篇文章主要介绍了golang动态创建类的实例代码,本文通过实例代码给大家讲解的非常详细,需要的朋友可以参考下
    2023-06-06
  • GoLang反射机制深入讲解

    GoLang反射机制深入讲解

    这篇文章主要介绍了GoLang反射机制,反射是一种让程序可以在运行时( runtime )检查其数据结构的能力,通过反射可以获取丰富的类型信息
    2022-12-12
  • 使用Go语言编写简洁代码的最佳实践

    使用Go语言编写简洁代码的最佳实践

    简洁的代码对于创建可维护、可阅读和高效的软件至关重要,Go 是一种强调简单和代码整洁的语言,在本文中,我们将结合代码示例,探讨编写简洁 Go 代码的最佳实践,需要的朋友可以参考下
    2023-09-09
  • Golang程序中使用Prometheus的client_golang库

    Golang程序中使用Prometheus的client_golang库

    这篇文章主要介绍了Golang程序中使用Prometheus的client_golang库,Prometheus 是一个开源的监控和警报工具包,用于收集和处理应用程序和系统的指标数据。Prometheus 提供了多种客户端库,可以轻松地集成到各种编程语言中
    2023-04-04
  • go mod tidy拉取依赖包bug问题及解决

    go mod tidy拉取依赖包bug问题及解决

    这篇文章主要介绍了go mod tidy拉取依赖包bug问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • Go slice切片使用示例详解

    Go slice切片使用示例详解

    这篇文章主要为大家介绍了Go slice切片使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • Go语言实现lru淘汰策略和超时过期

    Go语言实现lru淘汰策略和超时过期

    缓存的大小是有限的,当添加数据发现剩余缓存不够时,需要淘汰缓存中的部分数据,本文主要介绍了Go语言实现lru淘汰策略和超时过期,感兴趣的可以了解一下
    2024-02-02

最新评论