[英]Is the Go bytes.Buffer thread-safe?
不。
Go 文檔遵循一個簡單的規則:如果沒有明確聲明並發訪問某物是安全的,那么它就不是。
不 - 但您可以輕松地將它包裝在一個線程安全的結構中!
對於簡單的事情:
type Buffer struct {
b bytes.Buffer
m sync.Mutex
}
func (b *Buffer) Read(p []byte) (n int, err error) {
b.m.Lock()
defer b.m.Unlock()
return b.b.Read(p)
}
func (b *Buffer) Write(p []byte) (n int, err error) {
b.m.Lock()
defer b.m.Unlock()
return b.b.Write(p)
}
func (b *Buffer) String() string {
b.m.Lock()
defer b.m.Unlock()
return b.b.String()
}
..並像往常一樣使用它var buf Buffer
等。
想要更多 bytes.Buffer 嗎? 隨意挑選:
func (b *Buffer) Bytes() []byte {
b.m.Lock()
defer b.m.Unlock()
return b.b.Bytes()
}
func (b *Buffer) Cap() int {
b.m.Lock()
defer b.m.Unlock()
return b.b.Cap()
}
func (b *Buffer) Grow(n int) {
b.m.Lock()
defer b.m.Unlock()
b.b.Grow(n)
}
func (b *Buffer) Len() int {
b.m.Lock()
defer b.m.Unlock()
return b.b.Len()
}
func (b *Buffer) Next(n int) []byte {
b.m.Lock()
defer b.m.Unlock()
return b.b.Next(n)
}
func (b *Buffer) ReadByte() (c byte, err error) {
b.m.Lock()
defer b.m.Unlock()
return b.b.ReadByte()
}
func (b *Buffer) ReadBytes(delim byte) (line []byte, err error) {
b.m.Lock()
defer b.m.Unlock()
return b.b.ReadBytes(delim)
}
func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) {
b.m.Lock()
defer b.m.Unlock()
return b.b.ReadFrom(r)
}
func (b *Buffer) ReadRune() (r rune, size int, err error) {
b.m.Lock()
defer b.m.Unlock()
return b.b.ReadRune()
}
func (b *Buffer) ReadString(delim byte) (line string, err error) {
b.m.Lock()
defer b.m.Unlock()
return b.b.ReadString(delim)
}
func (b *Buffer) Reset() {
b.m.Lock()
defer b.m.Unlock()
b.b.Reset()
}
func (b *Buffer) Truncate(n int) {
b.m.Lock()
defer b.m.Unlock()
b.b.Truncate(n)
}
func (b *Buffer) UnreadByte() error {
b.m.Lock()
defer b.m.Unlock()
return b.b.UnreadByte()
}
func (b *Buffer) UnreadRune() error {
b.m.Lock()
defer b.m.Unlock()
return b.b.UnreadRune()
}
func (b *Buffer) WriteByte(c byte) error {
b.m.Lock()
defer b.m.Unlock()
return b.b.WriteByte(c)
}
func (b *Buffer) WriteRune(r rune) (n int, err error) {
b.m.Lock()
defer b.m.Unlock()
return b.b.WriteRune(r)
}
func (b *Buffer) WriteString(s string) (n int, err error) {
b.m.Lock()
defer b.m.Unlock()
return b.b.WriteString(s)
}
func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) {
b.m.Lock()
defer b.m.Unlock()
return b.b.WriteTo(w)
}
使用io.Pipe()
函數調用,它提供一對連接對象( *PipeReader
, *PipeWriter
)用於同步讀/寫。 這可以並行完成,並且它是線程安全的。
在Go編程語言中, bytes.Buffer
是線程安全的嗎? AFAIK,其文檔中沒有提及線程安全性。
bytes.Buffer 不是線程安全的,但這里有一個使用“通道和通信”安全地寫入 Buffer(或任何 io.StringWriter)的示例。
type SyncWriter struct {
w io.StringWriter
finish sync.WaitGroup
queue chan string
err error
}
func NewSyncWriter(w io.StringWriter) *SyncWriter {
var t SyncWriter
t.w = w
t.queue = make(chan string, 5)
t.finish.Add(1)
go t.writer()
return &t
}
func (t *SyncWriter) Close() error {
close(t.queue)
t.finish.Wait()
return t.err
}
func (t *SyncWriter) WriteString(s string) (int, error) {
t.queue <- s
return len(s), nil
}
func (t *SyncWriter) Write(p []byte) (int, error) {
return t.WriteString(string(p))
}
func (t *SyncWriter) writer() {
defer t.finish.Done()
for s := range t.queue {
_, err := t.w.WriteString(s)
if err != nil && t.err == nil {
t.err = err
}
}
}
下面是如何使用它:
func write(wg *sync.WaitGroup, w io.Writer, d int) {
fmt.Fprintf(w, "%d", d)
wg.Done()
}
func main() {
var buf bytes.Buffer
w := NewSyncWriter(&buf)
w.WriteString("hello ")
var wg sync.WaitGroup
wg.Add(10)
for i := 0; i < 10; i++ {
go write(&wg, w, i)
}
wg.Wait()
w.Close()
fmt.Printf("%s\n", buf.String())
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.