bufferredwrite(go语言string之Buffer与Builder)

:暂无数据 2026-04-20 16:40:01 0
还记得第一次接触bufferredwrite时的茫然吗?是go语言string之Buffer与Builder这个概念,像一盏灯照亮了后续的路。本文将为你点亮这盏灯。

本文目录

go语言string之Buffer与Builder

操作字符串离不开字符串的拼接,但是Go中string是只读类型,大量字符串的拼接会造成性能问题。

拼接字符串,无外乎四种方式,采用“+”,“fmt.Sprintf()”,"bytes.Buffer","strings.Builder"

上面我们创建10万字符串拼接的测试,可以发现"bytes.Buffer","strings.Builder"的性能最好,约是“+”的1000倍级别。

这是由于string是不可修改的,所以在使用“+”进行拼接字符串,每次都会产生申请空间,拼接,复制等操作,数据量大的情况下非常消耗资源和性能。而采用Buffer等方式,都是预先计算拼接字符串数组的总长度(如果可以知道长度),申请空间,底层是slice数组,可以以append的形式向后进行追加。最后在转换为字符串。这申请了不断申请空间的操作,也减少了空间的使用和拷贝的次数,自然性能也高不少。

bytes.buffer是一个缓冲byte类型的缓冲器存放着都是byte
是一个变长的 buffer,具有 Read 和Write 方法。 Buffer 的 零值 是一个 空的 buffer,但是可以使用,底层就是一个 byte, 字节切片。

向Buffer中写数据,可以看出Buffer中有个Grow函数用于对切片进行扩容。

从Buffer中读取数据

strings.Builder的方法和bytes.Buffer的方法的命名几乎一致。

但实现并不一致,Builder的Write方法直接将字符拼接slice数组后。

其没有提供read方法,但提供了strings.Reader方式

Reader 结构:

Buffer:

Builder:

可以看出Buffer和Builder底层都是采用byte数组进行装载数据。

先来说说Buffer:

创建好Buffer是一个empty的,off 用于指向读写的尾部。
在写的时候,先判断当前写入字符串长度是否大于Buffer的容量,如果大于就调用grow进行扩容,扩容申请的长度为当前写入字符串的长度。如果当前写入字符串长度小于最小字节长度64,直接创建64长度的byte数组。如果申请的长度小于二分之一总容量减去当前字符总长度,说明存在很大一部分被使用但已读,可以将未读的数据滑动到数组头。如果容量不足,扩展2*c + n 。

其String()方法就是将字节数组强转为string

Builder是如何实现的。

Builder采用append的方式向字节数组后添加字符串。

从上面可以看出,byte的内存大小也是以倍数进行申请的,初始大小为 0,第一次为大于当前申请的最大 2 的指数,不够进行翻倍.

可以看出如果旧容量小于1024进行翻倍,否则扩展四分之一。(2048 byte 后,申请策略的调整)。

其次String()方法与Buffer的string方法也有明显区别。Buffer的string是一种强转,我们知道在强转的时候是需要进行申请空间,并拷贝的。而Builder只是指针的转换。

这里我们解析一下 *(*string)(unsafe.Pointer(&b.buf)) 这个语句的意思。

先来了解下unsafe.Pointer 的用法。

也就是说,unsafe.Pointer 可以转换为任意类型,那么意味着,通过unsafe.Pointer媒介,程序绕过类型系统,进行地址转换而不是拷贝。

即*A =》 Pointer =》 *B

就像上面例子一样,将字节数组转为unsafe.Pointer类型,再转为string类型,s和b中内容一样,修改b,s也变了,说明b和s是同一个地址。但是对s重新赋值后,意味着s的地址指向了“WORLD”,它们所使用的内存空间不同了,所以s改变后,b并不会改变。

所以他们的区别就在于 bytes.Buffer 是重新申请了一块空间,存放生成的string变量, 而strings.Builder直接将底层的byte转换成了string类型返回了回来,去掉了申请空间的操作。

浅析nodejs的buffer比较怎么比较的

  • Buffer结构

Buffer是一个典型的Javascript和C++结合的模块,性能相关部分用C++实现,非性能相关部分用javascript实现。

Node在进程启动时Buffer就已经加装进入内存,并将其放入全局对象,因此无需require

Buffer对象:类似于数组,其元素是16进制的两位数。

Buffer内存分配

Buffer对象的内存分配不是在V8的堆内存中,在Node的C++层面实现内存的申请。

为了高效的使用申请来得内存,Node中采用slab分配机制,slab是一种动态内存管理机制,应用各种*nix操作系统。slab有三种状态:

(1) full:完全分配状态

(2) partial:部分分配状态

(3) empty:没有被分配状态

  • Buffer的转换
    Buffer对象可以和字符串相互转换,支持的编码类型如下:

ASCII、UTF-8、UTF-16LE/UCS-2、Base64、Binary、Hex

  • 字符串转Buffer

new Buffer(str, ),默认UTF-8
buf.write(string, )

  • Buffer转字符串

buf.toString()

Buffer不支持的编码类型

通过Buffer.isEncoding(encoding)判断是否支持

iconv-lite:纯JavaScript实现,更轻量,性能更好无需C++到javascript的转换

iconv:调用C++的libiconv库完成

  • Buffer的拼接

注意 "res.on(’data’, function(chunk) {})",其中的参数chunk是Buffer对象,直接用+拼接会自动转换为字符串,对于宽字节字符可能会导致乱码产生

  • 解决方法:

(1) 通过可读流中的setEncoding()方法,该方法可以让data事件传递不再是Buffer对象,而是编码后的字符串,其内部使用了StringEncoder模块。

(2) 将Buffer对象暂存到数组中,最后在组装成一个大Buffer让后编码转换为字符串输出。

Buffer在文件I/O和网络I/O中广泛应用,其性能举足轻重,比普通字符串性能要高出很多。

Buffer的使用除了与字符串的转换有性能损耗外,在文件读取时候,有一个highWaterMark设置对性能影响至关重要。

a,highWaterMark设置对Buffer内存的分配和使用有一定影响。

b, highWaterMark设置过小,可能导致系统调用次数过多。

什么时候该用buffer,什么时候不该用  ------ 纯粹的javascript支持unicode码而对二进制不是很支持,当解决TCP流或者文件流的时候,处理流是有必要的,我们保存非utf-8字符串,2进制等等其他格式的时候,我们就必须得使用 ”Buffer“ 。

is.read(buffer) 是什么意思

is应该是InputStream的缩写把,回去好好看看api read(bu f fer)中buffer是一个缓冲区 把数据先读到内存中,然后write(bu f fer,0,400)写道OutputStream中,每次都是从buffer内存处的0偏移开始写,每次写400字节。

探索bufferredwrite的旅程中,愿你对go语言string之Buffer与Builder的领悟能助你一臂之力。我们下期再见!
本文编辑:admin

更多文章:


java数字字符串(java语言中如何判断字符串是否为数字)

java数字字符串(java语言中如何判断字符串是否为数字)

本篇文章给大家谈谈java数字字符串,以及java语言中如何判断字符串是否为数字对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

2026年4月20日 18:20

java多线程和cpu的线程区别(在java中单线程和多线程是什么意思,他们有什么区别,分别的作用是什么)

java多线程和cpu的线程区别(在java中单线程和多线程是什么意思,他们有什么区别,分别的作用是什么)

你有没有想过,java多线程和cpu的线程区别的关键突破口,可能就藏在在java中单线程和多线程是什么意思,他们有什么区别,分别的作用是什么之中?本篇内容将为你验证这个猜想。

2026年4月20日 18:00

js字符串转化为数字类型(js 里面怎么把字符串转换成数字)

js字符串转化为数字类型(js 里面怎么把字符串转换成数字)

很多新手在接触js字符串转化为数字类型时,都会在js 里面怎么把字符串转换成数字这个问题上徘徊良久。本文将亮起指路明灯,带你快速通关。

2026年4月20日 17:40

特斯拉model y降价(特斯拉又降价新款Model Y曝光 全新包围+旋转中控)

特斯拉model y降价(特斯拉又降价新款Model Y曝光 全新包围+旋转中控)

很多朋友初次接触特斯拉model y降价可能会觉得有点陌生,这很正常。今天这篇文章,咱们就一起把特斯拉又降价新款Model Y曝光 全新包围+旋转中控这事儿聊透,希望能帮您理清思路。

2026年4月20日 17:20

梵谷 莫内 这是两个人是么他们是画画的么他们都有什么故事,不要太长,言简意赅就好?莫内莫奈

梵谷 莫内 这是两个人是么他们是画画的么他们都有什么故事,不要太长,言简意赅就好?莫内莫奈

曾几何时,我也觉得莫奈和莫内高不可攀,尤其梵谷 莫内 这是两个人是么他们是画画的么他们都有什么故事,不要太长,言简意赅就好更是一头雾水。后来才发现,只是没找对方法,希望我的经验能帮到你。

2026年4月20日 17:00

bufferredwrite(go语言string之Buffer与Builder)

bufferredwrite(go语言string之Buffer与Builder)

还记得第一次接触bufferredwrite时的茫然吗?是go语言string之Buffer与Builder这个概念,像一盏灯照亮了后续的路。本文将为你点亮这盏灯。

2026年4月20日 16:40

律师咨询免费24小时在线婚姻官司(离婚免费律师咨询在线24小时)

律师咨询免费24小时在线婚姻官司(离婚免费律师咨询在线24小时)

本文是您理解律师咨询免费24小时在线婚姻官司的最后一站。我们将通过剖析离婚免费律师咨询在线24小时,帮你打通任督二脉,彻底领悟。

2026年4月20日 16:20

100tablets是什么意思(tablets怎么读)

100tablets是什么意思(tablets怎么读)

面对100tablets是什么意思这个议题,很多人在tablets怎么读这里栽了跟头。今天,我们就来聊聊如何避免这个坑,轻松上手。

2026年4月20日 16:00

git bash命令(git bash怎么用cd命令切换路径写法)

git bash命令(git bash怎么用cd命令切换路径写法)

大家好,git bash命令相信很多的网友都不是很明白,包括git bash怎么用cd命令切换路径写法也是一样,不过没有关系,接下来就来为大家分享关于git bash命令和git bash怎么用cd命令切换路径写法的一些知识点,大家可以关注

2026年4月20日 15:40

pointer to different objects(同一项目文件的编译,在伟福下没有错误和警告,而在Keil下却有warning C182: pointer to different objects)

pointer to different objects(同一项目文件的编译,在伟福下没有错误和警告,而在Keil下却有warning C182: pointer to different objects)

本文是您理解pointer to different objects的最后一站。我们将通过剖析同一项目文件的编译,在伟福下没有错误和警告,而在Keil下却有warning C182: pointer to different objects

2026年4月20日 15:20

最近更新

bufferredwrite(go语言string之Buffer与Builder)
2026-04-20 16:40:01 浏览:0
100tablets是什么意思(tablets怎么读)
2026-04-20 16:00:02 浏览:0
pointer to different objects(同一项目文件的编译,在伟福下没有错误和警告,而在Keil下却有warning C182: pointer to different objects)
2026-04-20 15:20:02 浏览:0
热门文章

floatleft是什么意思(displayflex和floatleft的区别)
2026-04-17 04:40:03 浏览:0
androidbc(bc8-android是什么手机型号)
2026-04-05 07:20:02 浏览:0
标签列表