Go语言标准库_输入/输出

转载节选自《Go语言标准库》

Reader 接口

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

Read 将 len(p) 个字节读取到 p 中。它返回读取的字节数 n(0 <= n <= len(p)) 以及任何遇到的错误。即使 Read 返回的 n < len(p),它也会在调用过程中使用 p 的全部作为暂存空间。若一些数据可用但不到 len(p) 个字节,Read 会照例返回可用的数据,而不是等待更多数据。

当 Read 在成功读取 n > 0 个字节后遇到一个错误或 EOF (end-of-file),它就会返回读取的字节数。它会从相同的调用中返回(非nil的)错误或从随后的调用中返回错误(同时 n == 0)。 一般情况的一个例子就是 Reader 在输入流结束时会返回一个非零的字节数,同时返回的 err 不是 EOF 就是 nil。无论如何,下一个 Read 都应当返回 0, EOF。

调用者应当总在考虑到错误 err 前处理 n > 0 的字节。这样做可以在读取一些字节,以及允许的 EOF 行为后正确地处理 I/O 错误。

Writer

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

Write 将 len(p) 个字节从 p 中写入到基本数据流中。它返回从 p 中被写入的字节数 n(0 <= n <= len(p))以及任何遇到的引起写入提前停止的错误。若 Write 返回的 n < len(p),它就必须返回一个 非nil 的错误。

实现了 io.Reader 接口或 io.Writer 接口的类型

  • os.File 同时实现了 io.Reader 和 io.Writer
  • strings.Reader 实现了 io.Reader
  • bufio.Reader/Writer 分别实现了 io.Reader 和 io.Writer
  • bytes.Buffer 同时实现了 io.Reader 和 io.Writer
  • bytes.Reader 实现了 io.Reader
  • compress/gzip.Reader/Writer 分别实现了 io.Reader 和 io.Writer
  • crypto/cipher.StreamReader/StreamWriter 分别实现了 io.Reader 和 io.Writer
  • crypto/tls.Conn 同时实现了 io.Reader 和 io.Writer
  • encoding/csv.Reader/Writer 分别实现了 io.Reader 和 io.Writer
  • mime/multipart.Part 实现了 io.Reader

ReaderAt/WriterAt 接口

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

ReadAt 从基本输入源的偏移量 off 处开始,将 len(p) 个字节读取到 p 中。它返回读取的字节数 n(0 <= n <= len(p))以及任何遇到的错误。

当 ReadAt 返回的 n < len(p) 时,它就会返回一个 非nil 的错误来解释 为什么没有返回更多的字节。在这一点上,ReadAt 比 Read 更严格。

即使 ReadAt 返回的 n < len(p),它也会在调用过程中使用 p 的全部作为暂存空间。若一些数据可用但不到 len(p) 字节,ReadAt 就会阻塞直到所有数据都可用或产生一个错误。 在这一点上 ReadAt 不同于 Read。

若 n = len(p) 个字节在输入源的的结尾处由 ReadAt 返回,那么这时 err == EOF 或者 err == nil。

若 ReadAt 按查找偏移量从输入源读取,ReadAt 应当既不影响基本查找偏移量也不被它所影响。

ReadAt 的客户端可对相同的输入源并行执行 ReadAt 调用。

type WriterAt interface {
WriteAt(p []byte, off int64) (n int, err error)
}

WriteAt 从 p 中将 len(p) 个字节写入到偏移量 off 处的基本数据流中。它返回从 p 中被写入的字节数 n(0 <= n <= len(p))以及任何遇到的引起写入提前停止的错误。若 WriteAt 返回的 n < len(p),它就必须返回一个 非nil 的错误。

若 WriteAt 按查找偏移量写入到目标中,WriteAt 应当既不影响基本查找偏移量也不被它所影响。

若区域没有重叠,WriteAt 的客户端可对相同的目标并行执行 WriteAt 调用。

ReaderFrom/WriterTo 接口

type ReaderFrom interface {
ReadFrom(r Reader) (n int64, err error)
}

ReadFrom 从 r 中读取数据,直到 EOF 或发生错误。其返回值 n 为读取的字节数。除 io.EOF 之外,在读取过程中遇到的任何错误也将被返回。

如果 ReaderFrom 可用,Copy 函数就会使用它。

type WriterTo interface {
WriteTo(w Writer) (n int64, err error)
}

WriteTo 将数据写入 w 中,直到没有数据可写或发生错误。其返回值 n 为写入的字节数。 在写入过程中遇到的任何错误也将被返回。

如果 WriterTo 可用,Copy 函数就会使用它。

Seeker 接口

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

Seek 设置下一次 Read 或 Write 的偏移量为 offset,它的解释取决于 whence: 0 表示相对于文件的起始处,1 表示相对于当前的偏移,而 2 表示相对于其结尾处。 Seek 返回新的偏移量和一个错误,如果有的话。

whence 的值,在 os 包中定义了相应的常量,应该使用这些常量

const (
SEEK_SET int = 0 // seek relative to the origin of the file
SEEK_CUR int = 1 // seek relative to the current offset
SEEK_END int = 2 // seek relative to the end
)

Closer接口

type Closer interface {
Close() error
}

ByteReader 和 ByteWriter

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

在标准库中,有如下类型实现了 io.ByteReader 或 io.ByteWriter:

  • bufio.Reader/Writer 分别实现了io.ByteReader 和 io.ByteWriter
  • bytes.Buffer 同时实现了 io.ByteReader 和 io.ByteWriter
  • bytes.Reader 实现了 io.ByteReader
  • strings.Reader 实现了 io.ByteReader

ByteScanner、RuneReader 和 RuneScanner

type ByteScanner interface {
ByteReader
UnreadByte() error
}

UnreadByte 方法的意思是:将上一次 ReadByte 的字节还原,使得再次调用 ReadByte 返回的结果和上一次调用相同,也就是说,UnreadByte 是重置上一次的 ReadByte。注意,UnreadByte 调用之前必须调用了 ReadByte,且不能连续调用 UnreadByte。

ReadCloser、ReadSeeker、ReadWriteCloser、ReadWriteSeeker、ReadWriter、WriteCloser 和 WriteSeeker 接口

这些接口是上面介绍的接口的两个或三个组合而成的新接口。例如 ReadWriter 接口:

type ReadWriter interface {
Reader
Writer
}

SectionReader 类型

SectionReader 是一个 struct(没有任何导出的字段),实现了 Read, Seek 和 ReadAt,同时,内嵌了 ReaderAt 接口。结构定义如下:

type SectionReader struct {
r ReaderAt // 该类型最终的 Read/ReadAt 最终都是通过 r 的 ReadAt 实现
base int64 // NewSectionReader 会将 base 设置为 off
off int64 // 从 r 中的 off 偏移处开始读取数据
limit int64 // limit - off = SectionReader 流的长度
}

从名称我们可以猜到,该类型读取数据流中部分数据。看一下

func NewSectionReader(r ReaderAt, off int64, n int64) *SectionReader

的文档说明就知道了:

NewSectionReader 返回一个 SectionReader,它从 r 中的偏移量 off 处读取 n 个字节后以 EOF 停止。

PipeReader 和 PipeWriter 类型

PipeReader(一个没有任何导出字段的 struct)是管道的读取端。它实现了 io.Reader 和 io.Closer 接口。

关于 Read 方法的说明:从管道中读取数据。该方法会堵塞,直到管道写入端开始写入数据或写入端关闭了。如果写入端关闭时带上了 error(即调用 CloseWithError 关闭),该方法返回的 err 就是写入端传递的error;否则 err 为 EOF。

PipeWriter(一个没有任何导出字段的 struct)是管道的写入端。它实现了 io.Writer 和 io.Closer 接口。

关于 Write 方法的说明:写数据到管道中。该方法会堵塞,直到管道读取端读完所有数据或读取端关闭了。如果读取端关闭时带上了 error(即调用 CloseWithError 关闭),该方法返回的 err 就是读取端传递的error;否则 err 为 ErrClosedPipe。

Copy 和 CopyN 函数

func Copy(dst Writer, src Reader) (written int64, err error)

Copy 将 src 复制到 dst,直到在 src 上到达 EOF 或发生错误。它返回复制的字节数,如果有的话,还会返回在复制时遇到的第一个错误。

成功的 Copy 返回 err == nil,而非 err == EOF。由于 Copy 被定义为从 src 读取直到 EOF 为止,因此它不会将来自 Read 的 EOF 当做错误来报告。

若 dst 实现了 ReaderFrom 接口,其复制操作可通过调用 dst.ReadFrom(src) 实现。此外,若 src 实现了 WriterTo 接口,其复制操作可通过调用 src.WriteTo(dst) 实现。

func CopyN(dst Writer, src Reader, n int64) (written int64, err error)

CopyN 将 n 个字节从 src 复制到 dst。 它返回复制的字节数以及在复制时遇到的最早的错误。由于 Read 可以返回要求的全部数量及一个错误(包括 EOF),因此 CopyN 也能如此。

若 dst 实现了 ReaderFrom 接口,复制操作也就会使用它来实现。

ReadAtLeast 和 ReadFull 函数

func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error)

ReadAtLeast 将 r 读取到 buf 中,直到读了最少 min 个字节为止。它返回复制的字节数,如果读取的字节较少,还会返回一个错误。若没有读取到字节,错误就只是 EOF。如果一个 EOF 发生在读取了少于 min 个字节之后,ReadAtLeast 就会返回 ErrUnexpectedEOF。若 min 大于 buf 的长度,ReadAtLeast 就会返回 ErrShortBuffer。对于返回值,当且仅当 err == nil 时,才有 n >= min。

func ReadFull(r Reader, buf []byte) (n int, err error)

ReadFull 精确地从 r 中将 len(buf) 个字节读取到 buf 中。它返回复制的字节数,如果读取的字节较少,还会返回一个错误。若没有读取到字节,错误就只是 EOF。如果一个 EOF 发生在读取了一些但不是所有的字节后,ReadFull 就会返回 ErrUnexpectedEOF。对于返回值,当且仅当 err == nil 时,才有 n == len(buf)。

WriteString 函数

func WriteString(w Writer, s string) (n int, err error)

MultiReader 和 MultiWriter 函数

这两个函数的定义分别是:

func MultiReader(readers ...Reader) Reader
func MultiWriter(writers ...Writer) Writer

它们接收多个 Reader 或 Writer,返回一个 Reader 或 Writer。我们可以猜想到这两个函数就是操作多个 Reader 或 Writer 就像操作一个。

TeeReader函数

func TeeReader(r Reader, w Writer) Reader

Go语言标准库_输入/输出的更多相关文章

  1. 20200427_ls_正在读取目录_输入/输出错误

    环境: 在Centos7.2上挂载了一个2T的移动硬盘, 使用vim 在移动硬盘中编辑 .sh文件, wq的时候提示出错, 然后清空的文件, 可以正常wq出来 [root@localhost yido ...

  2. Python基本语法_输入/输出语句详解

    目录 目录 前言 输入 raw_input input raw_input 和 input 的区别 输出 print print 基本格式化输出 print复杂格式化输出 flags标志位 width ...

  3. 附录二 C语言标准库

    上章回顾 数组和指针相同与不同 通过指针访问数组和通过数组访问指针 指针在什么时候可以加减运算 函数指针的申明和调用 函数数组和数组函数 git@github.com:Kevin-Dfg/Data-S ...

  4. GO语言标准库—命令行参数解析FLAG

    flag包是Go语言标准库提供用来解析命令行参数的包,使得开发命令行工具更为简单 常用方法 1.flag.Usage 输出使用方法,如linux下ls -h的帮助输出 2.flag.Type(参数名, ...

  5. Go语言标准库之JSON编解码

    Go语言标准库之JSON编解码 基本的类型 Go语言中的数据类型和JSON的数据类型的关系 bool -> JSON boolean float64 -> JSON numbers str ...

  6. Go语言标准库之time

    Go语言标准库之time 时间的格式化和解析 格式化 Format Go语言和其他语言的时间格式化的方式不同,Go语言格式化的方式更直观,其他的语言一般是yyyy-mm-dd package main ...

  7. C 输入 & 输出——Day03

    当我们提到输入时,这意味着要向程序填充一些数据.输入可以是以文件的形式或从命令行中进行.C 语言提供了一系列内置的函数来读取给定的输入,并根据需要填充到程序中. 当我们提到输出时,这意味着要在屏幕上. ...

  8. C语言标准库之setjmp

    协程的介绍 协程(coroutine),意思就是“协作的例程”(co-operative routines),最早由Melvin Conway在1963年提出并实现.跟主流程序语言中的线程不一样,线程 ...

  9. C++——流类库和输入/输出

    前言 数据是怎么写道磁盘的? 代码里面我们一个读写调用似乎就能将数据从磁盘读写.仿佛代码是直接和磁盘打交道.以我们最常见的笔记本.或台式机的磁盘SATA盘为例,其受南桥上ATA控制器支配,这里面传输的 ...

随机推荐

  1. Java和Flex整合报错(三)

    1.错误描述 信息: Initializing Spring FrameworkServlet 'mvc' 11-13 23:43:42 INFO [localhost-startStop-1] or ...

  2. 芝麻HTTP:

    只要你的Scrapy Field字段名字和 数据库字段的名字 一样.那么恭喜你你就可以拷贝这段SQL拼接脚本.进行MySQL入库处理. 具体拼接代码如下: def process_item(self, ...

  3. idea好用插件(一)

    代码规范插件 Alibaba Java Coding Guidelines 安装后 可以在文件.文件夹邮件,显示编码规约扫描,点击后显示 可以通过双击定位问题代码,对某些问题可以进行快速的修复 比如: ...

  4. require()的工作流程

    require()的工作流程 当require()里传递一个参数x时,会有以下情况: x是一个文件 x是一个路径 eg. 当x为/home/dk/project/app 依次搜索以下的node_mod ...

  5. Python爬虫 股票数据爬取

    前一篇提到了与股票数据相关的可能几种数据情况,本篇接着上篇,介绍一下多个网页的数据爬取.目标抓取平安银行(000001)从1989年~2017年的全部财务数据. 数据源分析 地址分析 http://m ...

  6. Java微服务对UTC时间格式的处理

    一.背景 先说一下为什么要使用UTC时间.开发一个全球化的系统,服务端(Java微服务)集中部署在同一个地方,用户在全球通过浏览器.手机客户端访问.不同地区的时区是不一样的,同一个时间戳,不同的用户看 ...

  7. repo 和git的用法

    1. 服务器版本下载: repo init -u git@192.168.1.11:i700t_60501010/platform/manifest.git-b froyo_almond -m M76 ...

  8. 十大经典排序算法最强总结(含JAVA代码实现)

    最近几天在研究排序算法,看了很多博客,发现网上有的文章中对排序算法解释的并不是很透彻,而且有很多代码都是错误的,例如有的文章中在“桶排序”算法中对每个桶进行排序直接使用了Collection.sort ...

  9. python 全栈开发,Day3

    python之集合,深浅copy 一.集合 集合是无序的,不重复的数据集合,它里面的元素是可哈希的(不可变类型),但是集合本身是不可哈希(所以集合做不了字典的键)的.以下是集合最重要的两点: 去重,把 ...

  10. nginx的自动化安装和启停脚本

    个人原创,转载请注明出处和作者,否则依法追究法律责任 author: headsen chen date:  2018-03-07  14:39:11 nginx_install.sh #!/bin/ ...