Go标准库系列(四):基本的IO 接口

Reader接口

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

Read 将len(p)个字节读取到 p 中。它返回读取的字节数n(0 <= n <= len§)以及任何遇到的错误。
即使 Read 返回的 n < len§,它也会在调用过程中占用 len§ 个字节作为暂存空间。
若可读取的数据不到 len§ 个字节,Read 会返回可用数据,而不是等待更多数据。
当 Read 在成功读取 n > 0 个字节后遇到一个错误或 EOF (end-of-file),它会返回读取的字节数。它可能会同时在本次的调用中返回一个non-nil错误,或在下一次的调用中返回这个错误(且 n 为 0)。
一般情况下, Reader会返回一个非0字节数n, 若 n = len§ 个字节从输入源的结尾处由 Read 返回,Read可能返回 err = = EOF 或者 err == nil。并且之后的 Read() 都应该返回(n:0, err:EOF)
调用者在考虑错误之前应当首先处理返回的数据。这样做可以正确地处理在读取一些字节后产生的 I/O 错误,同时允许EOF的出现。

// ReadFrom以一个实现了Reader接口作为参数,也就是说它可以从任何地方读取数据, num表示读取几个字节
func ReadFrom(reader io.Reader, num int) ([]byte, error) {
	p :=make([]byte,num) //num用来定义p的大小
	n, err := reader.Read(p)
	if n > 0 {
		return p[:n], nil
	}
	return p, err
}

Writer 接口

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

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

标准输入输出流

//os.File同时实现了io.Writer/Reader
// 标准输入输出是他的实例
Stdin = NewFile(uintptr(syscall.Stdin),"/dev/stdin")
Stdout = NewFile(uintptr(syscall.Stdout),"/dev/stdout")
Stderr = NewFile(uintptr(syscall.Stderr),"/dev/stderr")

ReaderAt 和 WriterAt 接口

type ReaderAt interface {
    // 从基本输入源的偏移量 off 处开始,将 len(p) 个字节读取到 p 中
    ReadAt(p []byte, off int64) (n int, err error)
}

返回读取的字节数 n(0 <= n <= len§)以及任何遇到的错误。
当返回的 n < len§ 时,它就会返回一个 非nil 的错误来解释 为什么没有返回更多的字节。
它也会在调用过程中使用 p 的全部作为暂存空间。若可读取的数据不到 len§ 字节,ReadAt 就会阻塞,直到所有数据都可用或一个错误发生。
若 n = len§ 个字节从输入源的结尾处由 ReadAt 返回,Read可能返回 err = = EOF 或者 err == nil
若 ReadAt 携带一个偏移量从输入源读取**,ReadAt 应当既不影响偏移量也不被它所影响。**

type WriterAt interface {
    // 从 p 中将 len(p) 个字节写入到偏移量 off 处的基本数据流中
    WriteAt(p []byte, off int64) (n int, err error)
}

返回从 p 中被写入的字节数 n(0 <= n <= len§)以及任何遇到的引起写入提前停止的错误。
若 WriteAt 返回的 n < len§,它就必须返回一个 非nil 的错误。
若 WriteAt 携带一个偏移量写入到目标中,WriteAt 应当既不影响偏移量也不被它所影响。

ReaderFrom 和 WriterTo

type ReaderFrom interface {
	//从 r 中读取数据,直到 EOF 或发生错误
    ReadFrom(r Reader) (n int64, err error)
}

ReadFrom 方法不会返回 err == EOF。

type WriterTo interface {
    // 将数据写入 w 中,直到没有数据可写或发生错误
    WriteTo(w Writer) (n int64, err error)
}

Seeker

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

Seek 设置下一次 Read 或 Write 的偏移量为 offset,它的解释取决于 whence: 0 表示相对于文件的起始处,1 表示相对于当前的偏移,而 2 表示相对于其结尾处。 Seek 返回新的偏移量和一个错误,如果有的话。
Seek 方法是用于设置偏移量的,这样可以从某个特定位置开始操作数据流。

  • whence 的值,在 io 包中定义了相应的常量,应该使用这些常量
const (
  SeekStart   = 0 // seek relative to the origin of the file
  SeekCurrent = 1 // seek relative to the current offset
  SeekEnd     = 2 // seek relative to the end
)

Closer接口

type Closer interface {
    Close() error
}
  • 用于关闭数据流。
  • 文件 (os.File)、归档(压缩包)、数据库连接、Socket 等需要手动关闭的资源都实现了 Closer 接口。
  • 实际编程中,经常将 Close 方法的调用放在 defer 语句中。

ByteReader 和 ByteWriter:读或写一个字节

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

type ByteWriter interface {
    WriteByte(c byte) error
}

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 //将上一次ReadByte的字节还原
    //UnreadByte 调用之前必须调用了 ReadByte,且不能连续调用 UnreadByte
}
  • RuneReader 接口和 ByteReader 类似,只是 ReadRune 方法读取单个 UTF-8 字符,返回其 rune 和该字符占用的字节数。
  • RuneScanner 接口和 ByteScanner 类似

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 流的长度
}
//从 r 中的偏移量 off 处读取 n 个字节后以 EOF 停止。
func NewSectionReader(r ReaderAt, off int64, n int64) *SectionReader
// 方便重复操作某一段 (section) 数据流;或者同时需要 ReadAt 和 Seek 的功能。

LimitedReader 类型

type LimitedReader struct {
    R Reader // underlying reader,最终的读取操作通过 R.Read 完成
    N int64  //最多只能返回 N 字节数据
}

从 R 读取但将返回的数据量限制为 N 字节。每调用一次 Read 都将更新 N 来反应新的剩余数量。

PipeReader 和 PipeWriter 类型

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

type PipeReader struct {
    p *pipe
}

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

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

type PipeWriter struct {
    p *pipe
}

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

// io.Pipe() 用于创建一个同步的内存管道 (synchronous in-memory pipe)
func Pipe() (*PipeReader, *PipeWriter)

它将 io.Reader 连接到 io.Writer。一端的读取匹配另一端的写入,直接在这两端之间复制数据;

对于管道的 close 方法(非 CloseWithError 时),err 会被置为 EOF。

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 当做错误来报告。

ReadAtLeast 和 ReadFull 函数

// 将 r 读取到 buf 中,直到读了最少 min 个字节为止
func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error)
  • 它返回复制的字节数,如果读取的字节较少,还会返回一个错误。若没有读取到字节,错误就只是 EOF。
    • 如果一个 EOF 发生在读取了少于 min 个字节之后,ReadAtLeast 就会返回 ErrUnexpectedEOF。
    • 若 min 大于 buf 的长度,ReadAtLeast 就会返回 ErrShortBuffer。
// 精确地从 r 中将 len(buf) 个字节读取到 buf 中
func ReadFull(r Reader, buf []byte) (n int, err error)

WriteString 函数

// s的内容写入w中,当w实现了 WriteString 方法时,会直接调用该方法,否则执行 w.Write([]byte(s))
func WriteString(w Writer, s string) (n int, err error)

MultiReader 和 MultiWriter 函数

func MultiReader(readers ...Reader) Reader //在所有的 Reader 内容都被读完后,Reader 会返回 EOF。
func MultiWriter(writers ...Writer) Writer

type multiReader struct {
    readers []Reader
}
type multiWriter struct {
    writers []Writer
}

TeeReader函数

func TeeReader(r Reader, w Writer) Reader
  • TeeReader 返回一个 Reader,它将从 r 中读到的数据写入 w 中。所有经由它处理的从 r 的读取都匹配于对应的对 w 的写入。它没有内部缓存,即写入必须在读取完成前完成。任何在写入时遇到的错误都将作为读取错误返回。
    也就是说,我们通过 Reader 读取内容后,会自动写入到 Writer 中去。

你可能感兴趣的:(Go语言标准库基础)