Go语言核心36讲
郝林
《Go并发编程实战》作者,前轻松筹大数据负责人
立即订阅
24074 人已学习
课程目录
已完结 54 讲
0/4登录后,你可以任选4讲全文学习。
开篇词+学习路线 (3讲)
开篇词 | 跟着学,你也能成为Go语言高手
免费
预习篇 | 写给0基础入门的Go语言学习者
50 | 学习专栏的正确姿势
模块一:Go语言基础知识 (6讲)
01 | 工作区和GOPATH
02 | 命令源码文件
03 | 库源码文件
04 | 程序实体的那些事儿(上)
05 | 程序实体的那些事儿(中)
06 | 程序实体的那些事儿 (下)
模块二:Go语言进阶技术 (16讲)
07 | 数组和切片
08 | container包中的那些容器
09 | 字典的操作和约束
10 | 通道的基本操作
11 | 通道的高级玩法
12 | 使用函数的正确姿势
13 | 结构体及其方法的使用法门
14 | 接口类型的合理运用
15 | 关于指针的有限操作
16 | go语句及其执行规则(上)
17 | go语句及其执行规则(下)
18 | if语句、for语句和switch语句
19 | 错误处理(上)
20 | 错误处理 (下)
21 | panic函数、recover函数以及defer语句 (上)
22 | panic函数、recover函数以及defer语句(下)
模块三:Go语言实战与应用 (27讲)
23 | 测试的基本规则和流程 (上)
24 | 测试的基本规则和流程(下)
25 | 更多的测试手法
26 | sync.Mutex与sync.RWMutex
27 | 条件变量sync.Cond (上)
28 | 条件变量sync.Cond (下)
29 | 原子操作(上)
30 | 原子操作(下)
31 | sync.WaitGroup和sync.Once
32 | context.Context类型
33 | 临时对象池sync.Pool
34 | 并发安全字典sync.Map (上)
35 | 并发安全字典sync.Map (下)
36 | unicode与字符编码
37 | strings包与字符串操作
38 | bytes包与字节串操作(上)
39 | bytes包与字节串操作(下)
40 | io包中的接口和工具 (上)
41 | io包中的接口和工具 (下)
42 | bufio包中的数据类型 (上)
43 | bufio包中的数据类型(下)
44 | 使用os包中的API (上)
45 | 使用os包中的API (下)
46 | 访问网络服务
47 | 基于HTTP协议的网络服务
48 | 程序性能分析基础(上)
49 | 程序性能分析基础(下)
尾声与思考题答案 (2讲)
尾声 | 愿你披荆斩棘,所向无敌
新年彩蛋 | 完整版思考题答案
Go语言核心36讲
登录|注册

39 | bytes包与字节串操作(下)

郝林 2018-11-09
你好,我是郝林,今天我们继续分享 bytes 包与字节串操作的相关内容。
在上一篇文章中,我们分享了bytes.Buffer中已读计数的大致功用,并围绕着这个问题做了解析,下面我们来进行相关的知识扩展。

知识扩展

问题 1:bytes.Buffer的扩容策略是怎样的?

Buffer值既可以被手动扩容,也可以进行自动扩容。并且,这两种扩容方式的策略是基本一致的。所以,除非我们完全确定后续内容所需的字节数,否则让Buffer值自动去扩容就好了。
在扩容的时候,Buffer值中相应的代码(以下简称扩容代码)会先判断内容容器的剩余容量,是否可以满足调用方的要求,或者是否足够容纳新的内容。
如果可以,那么扩容代码会在当前的内容容器之上,进行长度扩充。
更具体地说,如果内容容器的容量与其长度的差,大于或等于另需的字节数,那么扩容代码就会通过切片操作对原有的内容容器的长度进行扩充,就像下面这样:
b.buf = b.buf[:length+need]
反之,如果内容容器的剩余容量不够了,那么扩容代码可能就会用新的内容容器去替代原有的内容容器,从而实现扩容。
不过,这里还有一步优化。
如果当前内容容器的容量的一半,仍然大于或等于其现有长度再加上另需的字节数的和,即:
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《Go语言核心36讲》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(9)

  • 失了智的沫雨
    如果只看strings.Builder 和bytes.Buffer的String方法的话,strings.Builder 更高效一些。
    我们可以直接查看两个String方法的源代码,其中strings.Builder String方法中
    *(*string)(unsafe.Pointer(&b.buf)) 是直接取得buf的地址然后转换成string返回。
    而bytes.Buffer的String方法是 string(b.buf[b.off:])
     对buf 进行切片操作,我认为这比直接取址要花费更多的时间。
    测试函数:
    func BenchmarkStrings(b *testing.B) {
    str := strings.Builder{}/bytes.Buffer{}
    str.WriteString("test")
    for i := 0; i < b.N; i++ {
    str.String()
    }
    }
    结果为
    BenchmarkStrings-8 2000000000 0.66 ns/op
    BenchmarkBuffer-8 300000000 5.64 ns/op
    所以strings.Builder的String方法更高效
    2018-11-11
    1
    14
  • 🤔
    https://github.com/golang/go/blob/master/src/strings/builder_test.go#L319-L366

    发现最后的问题,Go 的标准库中,已经给出了相关的测试代码了。
    2019-04-26
    1
  • 1thinc0
    bytes.Buffer 值的 String() 方法在转换时采用了指针 *(*string)(unsafe.Pointer(&b.buf)),更节省时间和内存
    2018-11-16
    1
  • cygnus
    ```
    func (b *Buffer) grow(n int) int {
            ......
    // Restore b.off and len(b.buf).
    b.off = 0
    b.buf = b.buf[:m+n]
    return m

    func (b *Buffer) Grow(n int) {
    if n < 0 {
    panic("bytes.Buffer.Grow: negative count")
    }
    m := b.grow(n)
    b.buf = b.buf[:m]
    }
    ```
    请问下老师,bytes.Buffer里grow函数返回前做过一次切片b.buf = b.buf[:m+n],返回后在Grow函数又做了一次切片b.buf = b.buf[:m],这样做的目的是什么呢?感觉有点冗余
    2018-11-13
    1
  • 骏Jero
    读了老师的两篇文章,strings.Builder更多是拼接数据和以及拼接完成后的读取使用上应该更适合。而buffer更为动态接受和读取数据时,更为高效。
    2018-11-09
    1
  • 窗外
    老师你好,为什么我本地的src/runtime包下的stringtoslicebyte方法里面tmpBuf的默认长度是32。
    所以文中例子,输出的容量是32

    作者回复: 你可以把前因后果都摆上来。这篇文章里有 tmpBuf 吗?

    2019-08-11
    1
  • rename
    如果当前内容容器的容量的一半,仍然大于或等于其现有长度再加上所需的字节数的和,即:cap(b.buf)/2 >= len(b.buf)+need
    这边len(b.buf)用b.Len()似乎更准确?才是获取未读部分的实际长度

    作者回复: 当然是要看 buf 本身的长度了。这是 bytes.Buffer 内部的算法,你可以看一看源码。

    2019-07-14
    1
  • 嘎嘎
    源码里给了推荐的构建方法
    // To build strings more efficiently, see the strings.Builder type.
    func (b *Buffer) String() string {
    if b == nil {
    // Special case, useful in debugging.
    return "<nil>"
    }
    return string(b.buf[b.off:])
    }

    作者回复: 这个Buffer类型比strings.Builder类型出现要早。我觉得后者质量更高一些。你可以参看一下后者的String方法。

    2019-03-15
  • 虢国技匠
    打卡
    2019-03-06
收起评论
9
返回
顶部