golang 之bytes.Buffer 写操作扩容解读 - Go语言中文社区

golang 之bytes.Buffer 写操作扩容解读


golang(go1.12.9) 的标准包bytes.Buffer,是一个简单的字节(byte) 缓冲buffer,
定义了一个默认的最小容量smallBufferSize = 64,实现了byte的读,写,清空等操作,
其中写操作稍微麻烦,需要考虑扩容的情形,下面主要分析一下buffer 扩容

首先,看一下buffer结构体的定义

type Buffer struct {
	buf      []byte // contents are the bytes buf[off : len(buf)]
	off      int    // read at &buf[off], write at &buf[len(buf)]
	lastRead readOp // last read operation, so that Unread* can work correctly.
}

buf : byte 切片,用来存储实际的数据,
off: 即offset 读操作的偏移地址
lastRead : 记录上一次的读操作类型

由此可以得出:

  • 读的偏移是在off,写的偏移是在L= buf[len(buf)] 处
  • 缓冲的有效数据的偏移在[off , L)区间 ,因为我们每读出一段数据,就要修改off,要保证off是读操作的第一个位置索引

buffer 扩容的具体实现

  • offset 是buffer 读偏移量
  • 设 m = buffer 的长度,即未读取的数据的长度 m = L - offset
  • L = buffer 底层slice的长度
  • c = cap(buffer) 底层slice的容量
当向buffer写入长度为n数据时,可能需要调整buffer的容量

扩容原则:
当slice的数据长度小于容量一半时,不扩容,反之,则容量扩大为原来的2倍

  • 1.如果 L + n < c 时,这时slice不需要扩容,(参考源码 tryGrowByReslice 函数)
    在这里插入图片描述

  • 2.当 L+n >= c 时, (参考源码 grow(n) 函数)需要分两种情况讨论

  • 2.1 如果写入数据之后buffer的长度小于slice容量的一半时 ,也就是m+n < c/2 时,
    此时我们用copy移动一下buffer的数据,再更新读的偏移量即可

在这里插入图片描述

  • 2.2 如果写入数据之后buffer的长度大于等于slice容量的一半时 ,也就是m+n >= c/2 时,此时需要两步
  • 2.2.1.扩大原来slice 的容量
    如果只是简单地将容量由c扩容至2c ,
    此时m+n >= c/2 ,有可能出现m+n >c 的情形,由于m < 2
    c ,则必有m+n < 2c +n ,
    所以我们只要将容量扩容至n+2
    c 即可满足要求
  • 2.2.2 用copy移动一下buffer的数据,再更新读的偏移量即可
    在这里插入图片描述
版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/u010301542/article/details/102131990
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢