Go语言 io包基本接口详解

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

微信搜索公众号[ 漫漫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路

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • 原文链接 http://ironxu.com/772 本文介绍Go 标准库 io 常用的导出函数,结构体和方法。 ...
    好刚编程阅读 1,379评论 0 9
  • io包中最重要的是两个接口:Reader和Writer Reader接口##### type Writer int...
    勿以浮沙筑高台阅读 16,260评论 0 5
  •  一般的,计算机程序是:输入 (Input) 经过算法处理产生输出 (Output)。各种语言一般都会提供IO库供...
    没我找不到电子书阅读 3,296评论 0 8
  • 先说一下接口,Go 语言中的接口很简单,在 Go 语言的 io 包中有这样一个函数: func ReadFull(...
    佛心看世界阅读 468评论 0 0
  • Reader接口 Reader 接口包装了基本的 Read 方法,用于输出自身的数据。Read 方法用于将对象的数...
    _羊羽_阅读 191评论 0 0