Golang中Buffer高效拼接字串以及自訂安全執行緒Buffer

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

Go中可以使用“+”合并字串,但是這種合并方式效率非常低,每合并一次,都是建立一個新的字串,就必須遍曆複製一次字串。Java中提供StringBuilder類(最高效,線程不安全)來解決這個問題。Go中也有類似的機制,那就是Buffer(線程不安全)。

以下是範例程式碼:
package mainimport (    "bytes"    "fmt")func main() {    var buffer bytes.Buffer    for 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 = 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不能讀也不能寫,效能好

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.