Go   发布时间:2022-04-09  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了Golang中Buffer高效拼接字符串以及自定义线程安全Buffer大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

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

以下是示例代码:@H_944_5@
package main

import (
    "bytes"
    "fmt"
)

func main() {
    var buffer bytes.buffer
    for i := 0; i < 1000; i++ {
        buffer.WriteString("a")
    }
    fmt.Println(buffer.String())
}

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

Buffer为什么线程不安全?

以下是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 = opInvalid
    m := 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 = opInvalid
    if 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 += n
    if n > 0 {
        b.lastRead = opRead
    }
    return
}

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

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

type Buffer struct {
    b bytes.buffer
    rw 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不能读也不能写,性能

大佬总结

以上是大佬教程为你收集整理的Golang中Buffer高效拼接字符串以及自定义线程安全Buffer全部内容,希望文章能够帮你解决Golang中Buffer高效拼接字符串以及自定义线程安全Buffer所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。