夜里睡不着,再写一篇
bufio主要包含的是带缓冲的IO操作,表面上看不难,但是源码研究下还是挺有意思的,来看看大佬是怎么写代码的,首先从Writer开始说
Writer
带缓冲的Writer图解
缓冲就像一个装水的瓶子,如果瓶子不满就可以一直往里面倒水。过程很生活化,可以看到这个倒水过程需要解决下面几个问题:
一、瓶子的容量是固定的,当前水位是不确定的,要随时准确记录
二、准备倒的水(C1)要和剩余的缓冲(C2)进行比较,根据比较结果进行后续操作
主要的原理就是上述两条,下面画个图直观看下
其中buf是一个[]byte,容量固定。n表示当前已缓存的容量,那么剩余容量 = len(buf) - n
方法:Write(p []byte)
func (b *Writer) Write(p []byte) (nn int, err error) { for len(p) > b.Available() && b.err == nil { var n int if b.Buffered() == 0 { n, b.err = b.wr.Write(p) } else { n = copy(b.buf[b.n:], p) b.n += n b.Flush() } nn += n p = p[n:] } if b.err != nil { return nn, b.err } n := copy(b.buf[b.n:], p) b.n += n nn += n return nn, nil }
解释:
1. 首先判断准备写入的字节数,如果大于剩余容量
1) 如果容器为空,则直接调用wr循环写入,这种情况下,缓冲区基本没有参与。
2) 如果容器剩余容量不为0,则先倒入然后执行Flush,剩余的继续比较。
2. 如果不大于剩余容量,则写入容器缓存起来
具体的算法就不再每步说明,看代码一目了然