42 | bufio包中的数据类型 (上)
今天,我们来讲另一个与 I/O 操作强相关的代码包bufio。bufio是“buffered I/O”的缩写。顾名思义,这个代码包中的程序实体实现的 I/O 操作都内置了缓冲区。
bufio包中的数据类型主要有:
1、Reader;
2、Scanner;
3、Writer和ReadWriter。
与io包中的数据类型类似,这些类型的值也都需要在初始化的时候,包装一个或多个简单 I/O 接口类型的值。(这里的简单 I/O 接口类型指的就是io包中的那些简单接口。)
下面,我们将通过一系列问题对bufio.Reader类型和bufio.Writer类型进行讨论(以前者为主)。今天我的问题是:bufio.Reader类型值中的缓冲区起着怎样的作用?
这道题的典型回答是这样的。
bufio.Reader类型的值(以下简称Reader值)内的缓冲区,其实就是一个数据存储中介,它介于底层读取器与读取方法及其调用方之间。所谓的底层读取器,就是在初始化此类值的时候传入的io.Reader类型的参数值。
Reader值的读取方法一般都会先从其所属值的缓冲区中读取数据。同时,在必要的时候,它们还会预先从底层读取器那里读出一部分数据,并暂存于缓冲区之中以备后用。
有这样一个缓冲区的好处是,可以在大多数的时候降低读取方法的执行时间。虽然,读取方法有时还要负责填充缓冲区,但从总体来看,读取方法的平均执行时间一般都会因此有大幅度的缩短。
问题解析
bufio.Reader类型并不是开箱即用的,因为它包含了一些需要显式初始化的字段。为了让你能在后面更好地理解它的读取方法的内部流程,我先在这里简要地解释一下这些字段,如下所示。
1、buf:[]byte类型的字段,即字节切片,代表缓冲区。虽然它是切片类型的,但是其长度却会在初始化的时候指定,并在之后保持不变。
2、rd:io.Reader类型的字段,代表底层读取器。缓冲区中的数据就是从这里拷贝来的。
3、r:int类型的字段,代表对缓冲区进行下一次读取时的开始索引。我们可以称它为已读计数。
4、w:int类型的字段,代表对缓冲区进行下一次写入时的开始索引。我们可以称之为已写计数。
5、err:error类型的字段。它的值用于表示在从底层读取器获得数据时发生的错误。这里的值在被读取或忽略之后,该字段会被置为nil。
6、lastByte:int类型的字段,用于记录缓冲区中最后一个被读取的字节。读回