Golang中Buffer高效拼接字符串以及自定义线程安全Buffer

news/2024/6/29 2:57:25

本文原创文章,转载注明出处,博客地址 https://segmentfault.com/u/to... 第一时间看后续精彩文章。觉得好的话,顺手分享到朋友圈吧,感谢支持。

Go中可以使用“+”合并字符串,但是这种合并方式效率非常低,每合并一次,都是创建一个新的字符串,就必须遍历复制一次字符串。Java中提供StringBuilder类(最高效,线程不安全)来解决这个问题。Go中也有类似的机制,那就是Buffer(线程不安全)。

以下是示例代码:
package mainimport ("bytes""fmt"
)func main() {var buffer bytes.Bufferfor i := 0; i < 1000; i++ {buffer.WriteString("a")}fmt.Println(buffer.String())
}

使用bytes.Buffer来组装字符串,不需要复制,只需要将添加的字符串放在缓存末尾即可。

Buffer为什么线程不安全?

The Go documentation follows a simple rule: If it is not explicitly stated that concurrent access to something is safe, it is not.

==Go文档遵循一个简单的规则:如果没有明确声明并发访问某事物是安全的,则不是。==

以下是Golang中bytes.Buffer部分源码
// A Buffer is a variable-sized buffer of bytes with Read and Write methods.
// The zero value for Buffer is an empty buffer ready to use.
type Buffer struct {buf       []byte   // contents are the bytes buf[off : len(buf)]off       int      // read at &buf[off], write at &buf[len(buf)]bootstrap [64]byte // memory to hold first slice; helps small buffers avoid allocation.lastRead  readOp   // last read operation, so that Unread* can work correctly.
}// Write appends the contents of p to the buffer, growing the buffer as
// needed. The return value n is the length of p; err is always nil. If the
// buffer becomes too large, Write will panic with ErrTooLarge.
func (b *Buffer) Write(p []byte) (n int, err error) {b.lastRead = opInvalidm := b.grow(len(p))return copy(b.buf[m:], p), nil
}// Read reads the next len(p) bytes from the buffer or until the buffer
// is drained. The return value n is the number of bytes read. If the
// buffer has no data to return, err is io.EOF (unless len(p) is zero);
// otherwise it is nil.
func (b *Buffer) Read(p []byte) (n int, err error) {b.lastRead = opInvalidif b.off >= len(b.buf) {// Buffer is empty, reset to recover space.b.Truncate(0)if len(p) == 0 {return}return 0, io.EOF}n = copy(p, b.buf[b.off:])b.off += nif n > 0 {b.lastRead = opRead}return
}

源码对于Buffer的定义中,并没有关于锁的字段,在write和read函数中也未发现锁的踪影,所以符合上面提到的文档中的rule,即Buffer并发是不安全的

如何自定义实现一个并发安全的Buffer

type Buffer struct {b bytes.Bufferrw sync.RWMutex
}
func (b *Buffer) Read(p []byte) (n int, err error) {b.rw.RLock()defer b.rw.RUnlock()return b.b.Read(p)
}
func (b *Buffer) Write(p []byte) (n int, err error) {b.rw.Lock()defer b.rw.Unlock()return b.b.Write(p)
}

通过读写锁,解决并发读写问题,以上提供了Read和Write函数,亲,是不是Golang代码简洁明了?其它函数可以在Golang关于Buffer源码的基础上自行实现

两种锁的区别
sync.Mutex(互斥锁)sync.RWMutex(读写锁)
当一个goroutine访问的时候,其他goroutine都不能访问,保证了资源的同步,避免了竞争,不过也降低了性能非写状态时:多个Goroutine可以同时读,一个Goroutine写的时候,其它Goroutine不能读也不能写,性能好

http://lihuaxi.xjx100.cn/news/239617.html

相关文章

java通用象棋游戏_在通用国际象棋界面周围模拟GraphQL包装器

java通用象棋游戏The Universal Chess Interface (UCI) has been around a long time and used by many chess engines. What does GraphQL bring to the mix?通用国际象棋界面(UCI)已经存在了很长时间&#xff0c;并且被许多国际象棋引擎使用。 GraphQL带来了什么&#xff1f…

长跑马拉松

需要控制节奏&#xff0c; 热身&#xff0c; 一开始要慢&#xff0c;节省体力 后期再发力 绝对不可以上来就发力转载于:https://www.cnblogs.com/brainstorm/p/7918936.html

山东计算机类好的民办大学,山东四大坑人学校-山东坑人的民办大学(野鸡大学)...

选择科目测一测我能上哪些大学选择科目领取你的专属报告>选择省份关闭请选择科目确定v>山东省作为高考大省&#xff0c;每年考生的竞争力很大&#xff0c;因此在选择院校的时候更需要考虑清楚。坊间传闻&#xff0c;“山东十大垃圾大学”是非常坑人的&#xff0c;那么山东…

graphpad做折线图后怎么保存_农村的干豆角怎么做的?农村妹子教你两个窍门,保存2年都不会坏...

农村经常制作的干豆角怎么做的&#xff1f;农村妹子教你两个窍门&#xff0c;保存到冬天炖肉吃夏季&#xff0c;这个时节正是豆角生长最旺盛的时候&#xff0c;在农村&#xff0c;只要种一小块地的豆角&#xff0c;都是吃不完的&#xff0c;如果不摘下来&#xff0c;就只能看着…

在线设计网站,有了这几个网站,设计再也不用求人了

不知道从什么时候开始设计已经不是一个很高深的专业&#xff0c;如果你是专门学习PS专门做平面设计的那么未来靠什么吃饭&#xff0c;不由不觉中陷入了冥想中... 想想那些年自己上学省吃俭用去学习&#xff0c;到现在能用到的时候几乎没有&#xff0c;最多就是公司改改发票&…

javascript晚绑定_JavaScript的应用,调用和绑定通过托管野餐来解释

javascript晚绑定by Kevin Kononenko凯文科诺年科(Kevin Kononenko) JavaScript的应用&#xff0c;调用和绑定通过托管野餐来解释 (JavaScript’s apply, call, and bind explained by hosting a cookout) If you have ever been in charge of operating the grill at a famil…

aspose.cells 无法读取公式值_隐藏 Excel表格、公式的9种方法

Excel&#xff0c;站在你面前&#xff0c;你却看不见.....1、给Excel文件穿上隐身衣在win10系统中&#xff0c;隐藏文件变得如此容易&#xff0c;选取文件点“隐藏所选项目”&#xff0c;再去掉“隐藏的项目”勾选 "&#xff08;想彻底隐藏需要修改注册表&#xff0c;新手…

Could not apply the stored configuration for monitors 解决办法

Could not apply the stored configuration for monitors 解决办法&#xff1a; $ sudo rm -rf ~/.config/monitors.xml 重启电脑即可 本文转自linux博客51CTO博客&#xff0c;原文链接http://blog.51cto.com/yangzhiming/1225802如需转载请自行联系原作者 yangzhimingg