Go 语言核心 36 讲
郝林
《Go 并发编程实战》作者,前轻松筹大数据负责人
79610 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 55 讲
Go 语言核心 36 讲
15
15
1.0x
00:00/00:00
登录|注册

38 | bytes包与字节串操作(上)

获取长度的方法
读回退的方法
截断内容的方法
写入内容的方法
读取内容的方法
获取长度时的作用
导出内容时的作用
重置内容时的作用
读回退时的作用
截断内容时的作用
写入内容时的作用
读取内容时的作用
与已读内容和未读内容相关
可拼接、截断、导出内容、顺序读取子序列
作为字节序列的缓冲区
下一篇文章的延展内容
bytes.Buffer类型的适用性
bytes.Buffer类型的方法
bytes.Buffer类型的已读计数
bytes.Buffer类型的长度和容量
bytes.Buffer类型的特色
strings包和bytes包的相似性
strings.Builderstrings.Reader类型
本次总结
上次总结
标题:bytes包与字节串操作(上)
参考文章

该思维导图由 AI 生成,仅供参考

我相信,经过上一次的学习,你已经对strings.Builderstrings.Reader这两个类型足够熟悉了。
我上次还建议你去自行查阅strings代码包中的其他程序实体。如果你认真去看了,那么肯定会对我们今天要讨论的bytes代码包,有种似曾相识的感觉。

前导内容: bytes.Buffer基础知识

strings包和bytes包可以说是一对孪生兄弟,它们在 API 方面非常的相似。单从它们提供的函数的数量和功能上讲,差别可以说是微乎其微。
只不过,strings包主要面向的是 Unicode 字符和经过 UTF-8 编码的字符串,而bytes包面对的则主要是字节和字节切片。
我今天会主要讲bytes包中最有特色的类型Buffer。顾名思义,bytes.Buffer类型的用途主要是作为字节序列的缓冲区。
strings.Builder类型一样,bytes.Buffer也是开箱即用的。
但不同的是,strings.Builder只能拼接和导出字符串,而bytes.Buffer不但可以拼接、截断其中的字节序列,以各种形式导出其中的内容,还可以顺序地读取其中的子序列。
可以说,bytes.Buffer是集读、写功能于一身的数据类型。当然了,这些也基本上都是作为一个缓冲区应该拥有的功能。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Go语言中的`bytes`包及其主要类型`Buffer`的特性和使用方法进行了深入讲解。`bytes.Buffer`类型在处理字节和字节切片时起到关键作用,其方法中大多数都用到了已读计数,影响着`Buffer`值的行为。在读取内容时,方法会根据已读计数判断内容容器中是否还有未读内容,并在读取完成后及时更新已读计数。写入内容时,方法会先检查内容容器是否有足够容量,若不足则进行扩容,并根据已读计数找到未读部分进行拷贝。截断内容的方法`Truncate`会根据已读计数和参数值确定内容容器的新总长度。`bytes.Buffer`的`Len`方法返回未读部分的长度,而`Bytes`方法和`String`方法的行为与`Len`方法一致。总结来说,`bytes.Buffer`是一个集读、写功能于一身的数据类型,适合作为字节序列的缓冲区。通过对`bytes.Buffer`源码的研究,读者可以更好地理解已读计数在`Buffer`值中的重要作用。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Go 语言核心 36 讲》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(15)

  • 最新
  • 精选
  • AllenGFLiu
    赫老師多次闡明源碼的重要性,但源碼內容的量確實不小。 不知道老師能不能給個閱讀源碼的路徑?

    作者回复: 如果想了解标准库中某个包的功能,可以从应用程序调用的函数看起,一步步深入。标准库是一张网,所以你在看的时候也需要织一张网,也就是说需要记好笔记,并且在必要的时候把那些点联结起来。这样才看得明白。

    2021-02-24
    3
    6
  • 盘胧
    花了2小时,一遍啃源码,一遍对照文章,一边自己写测试用例,一边搞官方包自己实现的用例。。。绝了,啃津津有味,不知不觉都天黑了

    作者回复: 👍

    2021-10-23
    3
  • lesserror
    郝林老师,以下问题,麻烦回答一下: 1. 「bytes.Buffer」 为什么不提供一个 Buffer值的已读计数值的获取方法呢? 2. 文中说: “在我们剖析了所有的相关方法之后,可以这样来总结:在已读计数代表的索引之前的那些内容,永远都是已经被读过的,它们几乎没有机会再次被读取”。我理解的是: 唯一有机会获取到这些内容的机会是 「UnreadByte」和 「UnreadRune」这两个方法吗? 3. 文中说:“这些已读内容所在的内存空间可能会被存入新的内容。这一般都是由于重置或者扩充内容容器导致的”。 已读的内容不是已经 复制给另外的变量返回给调用方了吗?为什么还会被被存入新的内容呢?没理解这句话的想表达的意思。

    作者回复: 1. 已读计数值属于内部状态,外界不需要知道啊。你想拿这个东西做什么用呢?该封装的就得封装起来,充分解耦。 2. 对的。 3. Buffer 在扩充自己时有可能会对数据进行压缩,也就是把未读的数据迁移到已读的那些元素槽位上。在这种情况下,如果经压缩后那些之前的“已读空间”中还有空位,那么新数据就可以存到那里。 另外,会导致“已读计数”变化的那些“读方法”读出去的是一个个数据元素(通过 copy 函数做的),而不是基于Buffer的切片。所以压缩数据并不会对已经读出去的那些数据造成影响。

    2021-08-24
    2
    2
  • NoTryNoSuccess
    坚持到这里了,给自己点赞!

    作者回复: 👍

    2019-08-31
    2
  • somenzz
    无法直接得到一个Buffer值的已读计数?? n, _ := buffer1.Read(p1) 这个 n 不就是已读取的字节数吗? 老师还说 buffer1的Len方法返回的也是内容容器中未被读取部分的长度,我认为是错的,buffer1的Len方法返回就是 buffer1 内的长度,只要读取了,就不会存在 buffer1 里面了,难道不是吗? 难道 buffer1 中还保留有已读取的字节吗?如果我错了,请老师给段代码证明下,buffer1 已读取的字节仍然可再次读取。

    作者回复: 不要自己认为,要去看Go的源码。源码面前无秘密! 而且咱们专栏的代码例子中也有相应的说明: https://github.com/hyper0x/Golang_Puzzlers/tree/master/src/puzzlers/article31 再多说一点吧,Read() 方法返回的 n 只是当次读取的字节数。另外 Len 方法的源码是这样的: func (b *Buffer) Len() int { return len(b.buf) - b.off } 这里的 b.off 代表的是读偏移量(相当于“读指针”),而 len(b.buf) 代表的是写偏移量(相当于“写指针”)。 另外,已读的那些字节并不会被马上删除掉,那样的话操作会太频繁(读时成本过高),它们是在写时发现需要增长缓存容量的时候才被删除掉的。 ** 编程工作第一大忌讳:只自己想象,不看源码。切记切记!!** 最后,对所有本专栏的读者说一句:读这个专栏,越往后越需要随看随查源码。这样才能够有深刻的理解和认识。

    2021-11-01
    2
    1
  • 盘胧
    学习源码以及使用的过程,按照作者写这个标准库的时候的思路:库函数 > 结构定义 > 结构函数 举例学习strings包: 1. 先熟悉外部库函数:go doc strings|grep "^func" 2. 熟悉对应的结构定义:go doc strings|grep "^type"|grep "struct" 3. 接下来就应该学习对应的内部结构的函数了 go doc strings.Builder|grep "^func" 可以使用思维导图,顺着函数的调用去看,把过程记录下来

    作者回复: 很好:)

    2021-10-23
    1
  • L.
    老师同学们好,请问一下大家手头有能够辅助阅读源码的书籍或者资料吗,有的包下边的源码实在是理解不了,有的是不理解整体逻辑,有的是不理解某一行的写法等等(小白求助

    作者回复: 可以进入我的知识星球“GoHackers VIP”然后向我提问(知识星球是一款App),当然也可以在这里向我提问。

    2020-05-12
    1
  • 静水流深
    一图胜千言
    2019-08-07
    3
    25
  • sket
    原来read把从缓冲区读的字节放到p1里面了,让我这个小白纠结了好半天
    2019-01-10
    1
    4
  • 传说中的成大大
    我去阅读了源码 发现重要的不止是 off 我暂且叫他偏移量 还有一个重要的字段lastRead 标识上一次是否是成功读取 和读了多少个字节 所以UnreadRune方法应该还是可以正常使用吧(不包含ReadRune的情况) 毕竟底层是b.off -= int(b.lastRead)
    2020-04-29
    1
    1
收起评论
显示
设置
留言
15
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部