38 | bytes包与字节串操作(上)
该思维导图由 AI 生成,仅供参考
前导内容: bytes.Buffer基础知识
- 深入了解
- 翻译
- 解释
- 总结
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-2436 - 盘胧花了2小时,一遍啃源码,一遍对照文章,一边自己写测试用例,一边搞官方包自己实现的用例。。。绝了,啃津津有味,不知不觉都天黑了
作者回复: 👍
2021-10-233 - lesserror郝林老师,以下问题,麻烦回答一下: 1. 「bytes.Buffer」 为什么不提供一个 Buffer值的已读计数值的获取方法呢? 2. 文中说: “在我们剖析了所有的相关方法之后,可以这样来总结:在已读计数代表的索引之前的那些内容,永远都是已经被读过的,它们几乎没有机会再次被读取”。我理解的是: 唯一有机会获取到这些内容的机会是 「UnreadByte」和 「UnreadRune」这两个方法吗? 3. 文中说:“这些已读内容所在的内存空间可能会被存入新的内容。这一般都是由于重置或者扩充内容容器导致的”。 已读的内容不是已经 复制给另外的变量返回给调用方了吗?为什么还会被被存入新的内容呢?没理解这句话的想表达的意思。
作者回复: 1. 已读计数值属于内部状态,外界不需要知道啊。你想拿这个东西做什么用呢?该封装的就得封装起来,充分解耦。 2. 对的。 3. Buffer 在扩充自己时有可能会对数据进行压缩,也就是把未读的数据迁移到已读的那些元素槽位上。在这种情况下,如果经压缩后那些之前的“已读空间”中还有空位,那么新数据就可以存到那里。 另外,会导致“已读计数”变化的那些“读方法”读出去的是一个个数据元素(通过 copy 函数做的),而不是基于Buffer的切片。所以压缩数据并不会对已经读出去的那些数据造成影响。
2021-08-2422 - NoTryNoSuccess坚持到这里了,给自己点赞!
作者回复: 👍
2019-08-312 - 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-0121 - 盘胧学习源码以及使用的过程,按照作者写这个标准库的时候的思路:库函数 > 结构定义 > 结构函数 举例学习strings包: 1. 先熟悉外部库函数:go doc strings|grep "^func" 2. 熟悉对应的结构定义:go doc strings|grep "^type"|grep "struct" 3. 接下来就应该学习对应的内部结构的函数了 go doc strings.Builder|grep "^func" 可以使用思维导图,顺着函数的调用去看,把过程记录下来
作者回复: 很好:)
2021-10-231 - L.老师同学们好,请问一下大家手头有能够辅助阅读源码的书籍或者资料吗,有的包下边的源码实在是理解不了,有的是不理解整体逻辑,有的是不理解某一行的写法等等(小白求助
作者回复: 可以进入我的知识星球“GoHackers VIP”然后向我提问(知识星球是一款App),当然也可以在这里向我提问。
2020-05-121 - 静水流深一图胜千言2019-08-07325
- sket原来read把从缓冲区读的字节放到p1里面了,让我这个小白纠结了好半天2019-01-1014
- 传说中的成大大我去阅读了源码 发现重要的不止是 off 我暂且叫他偏移量 还有一个重要的字段lastRead 标识上一次是否是成功读取 和读了多少个字节 所以UnreadRune方法应该还是可以正常使用吧(不包含ReadRune的情况) 毕竟底层是b.off -= int(b.lastRead)2020-04-2911