Golang 中的 Bytes 包詳解之 Bytes.Buffer
Golang 中的 bytes 包是其中一個 IO 操作標準庫,實現了對字節切片([]byte)的操作,提供了類似于 strings 包的功能。本文先講解一下 bytes 包中的結構體 bytes.Buffer。
bytes.Buffer
bytes.Buffer 實現了 io.Writer、io.Reader、io.ByteScanner、io.RuneScanner、io.WriterTo、io.ByteWriter 和 io.ReaderFrom 等接口,可以很方便地實現對字節數據的讀寫和操作。主要特點是提供了一個緩沖區,可以在內存中動態分配緩沖區,以高效地寫入和讀取字節數據。在處理數據時,特別是數據拼接操作時,效率往往比直接使用字符串拼接要高很多。結構體定義和對應的方法如下:
type Buffer struct {
buf []byte // contents are the bytes buf[off : len(buf)]
off int // read at &buf[off], write at &buf[len(buf)]
lastRead readOp // last read operation, so that Unread* can work correctly.
}
其中,buf 保存了實際的字節緩存,off 表示下一個讀寫操作的偏移量,lastRead 表示最后一次讀取操作的類型和大小。
bytes.Buffer 提供的主要方法包括:
- ReadFrom,從 io.Reader 中讀取數據,并寫入到緩沖區中。
- WriteTo,從緩沖區中讀取數據,并寫入到 io.Writer 中。
- WriteByte、WriteRune、WriteString,分別用于將單個字節、Unicode 字符和字符串寫入緩沖區中。
- ReadByte、ReadRune、ReadString,分別用于從緩沖區中讀取單個字節、Unicode 字符和字符串。
- Bytes、String,返回緩沖區中的字節切片和字符串。
- Reset,用于重置緩沖區,將其擴容為默認大小(64 字節)。
其他方法就不一一說明了,最好自己去看去使用去體會。
使用示例
簡單使用示例如下:
package main
import (
"bytes"
"encoding/binary"
"fmt"
"io"
"os"
)
func main() {
var buf bytes.Buffer
// 寫入一個字節
err := buf.WriteByte('a')
if err != nil {
fmt.Println(err)
return
}
// 寫入一個字符串
_, err = buf.WriteString("b")
if err != nil {
fmt.Println(err)
return
}
// 寫入一個無符號整數
var u uint32 = 12345
err = binary.Write(&buf, binary.LittleEndian, u)
if err != nil {
fmt.Println(err)
return
}
// 讀取一個字節
b, err := buf.ReadByte()
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(b)) // a
// 讀取一個字符串
s, err := buf.ReadString('\n')
if err != nil {
fmt.Println(err)
return
}
fmt.Println(s) // b
// 讀取無符號整數
var u2 uint32
err = binary.Read(&buf, binary.LittleEndian, &u2)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(u2) // 12345
// 拷貝到標準輸出中
_, err = io.Copy(os.Stdout, &buf)
if err != nil {
fmt.Println(err)
return
}
// 讀取到 []byte 中,并以字符串輸出
data, err := io.ReadAll(&buf)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(data))
}
首先創建了一個 bytes.Buffer 對象 buf,分別使用 WriteByte、WriteString 和 binary.Write 方法向緩沖區中寫入一個字節、一個字符串和一個無符號整數。然后分別使用 ReadByte、ReadString 和 binary.Read 方法從緩沖區中讀取了一個字節、一個字符串和一個無符號整數。接下來使用 io.Copy 方法和 os.Stdout 將緩沖區中的數據拷貝到標準輸出中,最后使用 io.ReadAll 方法將緩沖區中的所有數據讀取到一個字節切片中,并轉換為一個字符串。
小結
使用 bytes.Buffer 可以方便高效地處理字節數據,避免頻繁地對底層的字節數組進行擴容和復制,從而提高性能。