构造
type Writer struct {
err error
// 输出缓冲区
buf []byte
// 缓冲区写到哪了
n int
// 被包装的writer
wr io.Writer
}
buf是缓冲区,其中buf[0:n]表示装已经写了的数据,buf[n:] 表示还可以写的空间
Available:缓冲区是否还有剩余空间可写
如果n到最后了,说明没位置可写了
func (b *Writer) Available() int { return len(b.buf) - b.n }
WriteString
整体流程比较直白:
- 如果缓冲区够写,就把字符串s写到缓冲区,返回
- 否则剩下的缓冲区不够写完整的s,就先写一部分,把缓冲区填满,调Flush方法把缓冲区的全部数据写到真正的writer中
- 再把s剩下的部分写到缓冲区中
func (b *Writer) WriteString(s string) (int, error) {
var sw io.StringWriter
tryStringWriter := true
nn := 0
// 剩余的缓冲区不够写s了
for len(s) > b.Available() && b.err == nil {
var n int
// 先把s的一部分拷贝到buf中
n = copy(b.buf[b.n:], s)
b.n += n
// 调真正的writer把buf的数据写出去
b.Flush()
nn += n
// 扣减本次写过的部分,for循环下次写剩下的部分
s = s[n:]
}
if b.err != nil {
return nn, b.err
}
// 到这说明缓存空间还够写s,那就把s完整复制到buf中
n := copy(b.buf[b.n:], s)
b.n += n
nn += n
return nn, nil
}
Flush
将缓冲区中的所有数据调真正的writer写出去,然后清空缓冲区
func (b *Writer) Flush() error {
if b.err != nil {
return b.err
}
if b.n == 0 {
return nil
}
// 调真正的writer,写buf中的所有数据
n, err := b.wr.Write(b.buf[0:b.n])
if n < b.n && err == nil {
err = io.ErrShortWrite
}
if err != nil {
// 返回err,但写成功了一部分,写成功的这部分从缓冲区移除
if n > 0 && n < b.n {
copy(b.buf[0:b.n-n], b.buf[n:b.n])
}
b.n -= n
b.err = err
return err
}
// 写完后清空buf
b.n = 0
return nil
}