美文网首页
Go语言 io包基本接口详解

Go语言 io包基本接口详解

作者: 漫漫Coding路 | 来源:发表于2021-12-22 09:30 被阅读0次

    你必须非常努力,才能看起来毫不费力!

    微信搜索公众号[ 漫漫Coding路 ],一起From Zero To Hero !

    前言

    IO 操作是我们在编程中不可避免会遇到的,例如读写文件,Go语言的 io 包中提供了相关的接口,定义了相应的规范,不同的数据类型可以根据规范去实现相应的方法,提供更加丰富的功能。

    Go 语言提倡小接口 + 接口组合的方式,来扩展程序的行为以及增加程序的灵活性。io代码包恰恰就可以作为这样的一个标杆,它可以成为我们运用这种技巧时的一个参考标准。

    上一篇文章,我们学习了io包中的四个核心接口,本篇文章我们来学习下多个基本接口!

    ReaderFrom

    io.ReaderFrom 接口定义了 ReadFrom 方法,用于从一个 Reader 中读取数据

    • 入参:Reader r
    • 返回值:n为读取的字节数,err 为读取过程中遇到的error
    type ReaderFrom interface {
        ReadFrom(r Reader) (n int64, err error)
    }
    

    方法功能详解

    1. 该方法从 Reader r 中读取数据,直到读到文件末尾(EOF)或者 遇到 其他 error
    2. 返回的 n 就是读取的字节数

    WriterTo

    io.WriteTo 接口定义了 WriteTo 方法,用于将数据写入到一个 Writer 中

    • 入参:Writer w
    • 返回值:n为写入的字节数,err 为写入过程中遇到的 error
    type WriterTo interface {
       WriteTo(w Writer) (n int64, err error)
    }
    

    方法功能详解

    1. 该方法将数据写入到 w 中,直到没有数据可写或者遇到error
    2. 返回的 n 就是写入的字节数

    ReaderAt

    io.ReaderAt 接口定义了 ReadAt 方法,用于从指定位置读取数据

    • 入参:读取的起始位置 off,读取后写入字节数组 p
    • 返回值:n 为成功读取的字节数,err为读取过程中遇到的 error
    type ReaderAt interface {
        ReadAt(p []byte, off int64) (n int, err error)
    }
    

    方法功能详解

    1. 方法从指定的偏移量位置 off 开始读取指定的数据,然后至多读取 len(p) 个字节,写入字节数组 p
    2. 返回成功读取的字节量 n,以及遇到的 error
    3. 当该方法返回的 n < len(p) 时,即读取的数据没有将字节数组p填充满,返回的 err != nil,在这一点上,ReadAt方法要比 Read方法严格(Read方法规定遇到n<len(p),本次调用可以返回 err=nil,然后在下一次调用时返回err!=nil )
    4. 即使方法返回的 n < len(p),也可能会占用整个字节数组 p 作为暂存空间
    5. 如果数据可用,但是不够 len(p)个字节,ReadAt 方法会阻塞,直到所有数据可用 或者 遇到 error,这一点也与 Read 方法不同
    6. 如果方法返回的 n=len(p),并且此时正好读取到了文件末尾,ReadAt 可以返回 err = EOF 或者 err = nil。如果返回的 err 为 nil的话,下次就一定返回 EOF 了。

    不能影响seek offset

    1. 如果 ReadAt 方法的入参 off 是由 seek 方法计算得到的,ReadAt 方法不能修改 off 的值

    可并行

    1. 对于同一个数据源,可以并行调用 ReadAt 方法读取数据

    方法实现需注意

    1. 实现该方法后,一定不要持有字节数组p(不能保存 p 的地址,用于其他地方)

    WriteAt

    io.WriterAt 接口定义了 WriteAt 方法,将字节数组 p 中的数据,从文件 off 偏移量开始写入到文件中

    • 入参:字节数组p,文件开始写处的偏移量 off
    • 返回值:成功写入的字节数 n,写入过程中遇到的error err
    type WriterAt interface {
        WriteAt(p []byte, off int64) (n int, err error)
    }
    

    方法功能详解

    1. 方法将 字节数组 p 中的 len(p) 个字节,从文件 off 位置开始,写入到文件中。
    2. 方法返回成功写入的字节个数n (0 <= n <= len(p)) ,以及是否遇到 error
    3. 如果 n < len(p),方法必须返回 err!=nil

    不能影响offset

    1. 如果 WriteAt 方法的入参 off 是由 seek 方法计算得到的,ReadAt 方法不能修改 off 的值

    可并行

    1. 对于同一个数据源,如果写入的范围不重叠,可以并行调用 WriteAt 方法写数据

    方法实现需注意

    1. 实现该方法后,一定不要持有字节数组p(不能保存 p 的地址,用于其他地方)

    ByteReader

    io.ByteReader 接口定义了 ReadByte 方法,用于读取一个字节

    • 返回值:读取的一个字节,以及可能遇到的 error
    type ByteReader interface {
       ReadByte() (byte, error)
    }
    

    方法功能详解

    1. 方法读取底层数据流的下一个字节,然后返回该字节,同时返回对应的error
    2. 如果方法读取过程中遇到error,不会消费底层数据的一个字节,相当于当前读取的位置不会变

    ByteScanner

    ByteScanner 是 ByteReader 接口 和 UnreadByte 方法的组合,因此该组合接口包含了两个方法,一个 ReadByte,一个 UnreadByte。从名字我们也可以看出来,ReadByte 是读取一个字节,UnreadByte 是回退一个字节。

    type ByteScanner interface {
       ByteReader
       UnreadByte() error
    }
    

    方法功能详解

    1. 在调用一次 ReadByte 之后,如果调用一次 UnreadByte,那么下次再调用 ReadByte 方法得到的值,和第一次调用 ReadByte 应该一样,也就是回退了一个位置。
    2. 如果连续两次调用 UnreadByte,中间没有调用 ReadByte,可能会产生 error (这里说的可能,比如从文件开始读取一次,然后两次回退,那么回退到的位置可能就不合法了,具体还是依赖实现方法定义)

    ByteWriter

    io.ByteWriter 接口定义了 WriteByte 方法,用于向底层文件写入一个字节,然后返回写入过程产生的 error

    type ByteWriter interface {
        WriteByte(c byte) error
    }
    

    RuneReader

    io.RuneReader 接口定义了 ReadRune 方法,读取一个 UTF-8 字符。UTF-8 是一种变长编码规则,从 1 到 4 个字节不等,比如一个字母占一个字节,中文每个字符占用 3 个字节。ReadRune 每次读出的是一个完整的编码字符,比如读汉字,每次就会读出一个汉字。

    type RuneReader interface {
        ReadRune() (r rune, size int, err error)
    }
    

    RuneScanner

    类似 ByteScanner,RuneScanner 也是个组合接口,提供了 UnreadRune 方法,可以回退一个 rune。如果连续两次调用 UnreadRune 方法,可能会产生error。

    type RuneScanner interface {
        RuneReader
        UnreadRune() error
    }
    

    StringWriter

    io.StringWriter 接口定义了 WriteString 方法,用于将字符串 s 写入底层的数据流中,返回写入成功的字节数 n,以及可能产生的 error

    // StringWriter is the interface that wraps the WriteString method.
    type StringWriter interface {
       WriteString(s string) (n int, err error)
    }
    

    总结

    本篇文章介绍了 io包 中的十个基本接口及对应的方法:

    • ReaderFrom: 定义了 ReadFrom 方法,从 Reader 中读取数据
    • WriterTo: 定义了 WriteTo 方法,向 Writer 中写入数据
    • ReaderAt: 定义了 ReadAt 方法,从指定位置读取数据
    • WriterAt: 定义了 WriteAt 方法,从指定位置写入数据
    • ByteReader: 定义了 ReadByte 方法,读取一个字节
    • ByteScanner: 组合接口,除了ReadByte 方法,定义了 UnreadByte 方法,用于回退一个字节
    • ByteWriter: 定义了 WriteByte 方法,向文件写入一个字节
    • RuneReader: 定义了 ReadRune 方法,读取一个 UTF-8 字符
    • RuneScanner: 组合接口,除了 ReadRune 方法,定义了 UnreadRune 方法,用于回退一个 rune
    • StringWriter: 定义了 WriteString 方法,用于向文件写入一个字符串

    更多

    个人博客: https://lifelmy.github.io/

    微信公众号:漫漫Coding路

    相关文章

      网友评论

          本文标题:Go语言 io包基本接口详解

          本文链接:https://www.haomeiwen.com/subject/xjcqqrtx.html