Golang 中的 Bytes 包詳解之 Bytes.Buffer
Golang 中的 bytes 包是其中一個(gè) IO 操作標(biāo)準(zhǔn)庫(kù),實(shí)現(xiàn)了對(duì)字節(jié)切片([]byte)的操作,提供了類似于 strings 包的功能。本文先講解一下 bytes 包中的結(jié)構(gòu)體 bytes.Buffer。
bytes.Buffer
bytes.Buffer 實(shí)現(xiàn)了 io.Writer、io.Reader、io.ByteScanner、io.RuneScanner、io.WriterTo、io.ByteWriter 和 io.ReaderFrom 等接口,可以很方便地實(shí)現(xiàn)對(duì)字節(jié)數(shù)據(jù)的讀寫(xiě)和操作。主要特點(diǎn)是提供了一個(gè)緩沖區(qū),可以在內(nèi)存中動(dòng)態(tài)分配緩沖區(qū),以高效地寫(xiě)入和讀取字節(jié)數(shù)據(jù)。在處理數(shù)據(jù)時(shí),特別是數(shù)據(jù)拼接操作時(shí),效率往往比直接使用字符串拼接要高很多。結(jié)構(gòu)體定義和對(duì)應(yīng)的方法如下:
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 保存了實(shí)際的字節(jié)緩存,off 表示下一個(gè)讀寫(xiě)操作的偏移量,lastRead 表示最后一次讀取操作的類型和大小。
bytes.Buffer 提供的主要方法包括:
- ReadFrom,從 io.Reader 中讀取數(shù)據(jù),并寫(xiě)入到緩沖區(qū)中。
- WriteTo,從緩沖區(qū)中讀取數(shù)據(jù),并寫(xiě)入到 io.Writer 中。
- WriteByte、WriteRune、WriteString,分別用于將單個(gè)字節(jié)、Unicode 字符和字符串寫(xiě)入緩沖區(qū)中。
- ReadByte、ReadRune、ReadString,分別用于從緩沖區(qū)中讀取單個(gè)字節(jié)、Unicode 字符和字符串。
- Bytes、String,返回緩沖區(qū)中的字節(jié)切片和字符串。
- Reset,用于重置緩沖區(qū),將其擴(kuò)容為默認(rèn)大?。?4 字節(jié))。
其他方法就不一一說(shuō)明了,最好自己去看去使用去體會(huì)。
使用示例
簡(jiǎn)單使用示例如下:
package main
import (
"bytes"
"encoding/binary"
"fmt"
"io"
"os"
)
func main() {
var buf bytes.Buffer
// 寫(xiě)入一個(gè)字節(jié)
err := buf.WriteByte('a')
if err != nil {
fmt.Println(err)
return
}
// 寫(xiě)入一個(gè)字符串
_, err = buf.WriteString("b")
if err != nil {
fmt.Println(err)
return
}
// 寫(xiě)入一個(gè)無(wú)符號(hào)整數(shù)
var u uint32 = 12345
err = binary.Write(&buf, binary.LittleEndian, u)
if err != nil {
fmt.Println(err)
return
}
// 讀取一個(gè)字節(jié)
b, err := buf.ReadByte()
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(b)) // a
// 讀取一個(gè)字符串
s, err := buf.ReadString('\n')
if err != nil {
fmt.Println(err)
return
}
fmt.Println(s) // b
// 讀取無(wú)符號(hào)整數(shù)
var u2 uint32
err = binary.Read(&buf, binary.LittleEndian, &u2)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(u2) // 12345
// 拷貝到標(biāo)準(zhǔn)輸出中
_, 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))
}
首先創(chuàng)建了一個(gè) bytes.Buffer 對(duì)象 buf,分別使用 WriteByte、WriteString 和 binary.Write 方法向緩沖區(qū)中寫(xiě)入一個(gè)字節(jié)、一個(gè)字符串和一個(gè)無(wú)符號(hào)整數(shù)。然后分別使用 ReadByte、ReadString 和 binary.Read 方法從緩沖區(qū)中讀取了一個(gè)字節(jié)、一個(gè)字符串和一個(gè)無(wú)符號(hào)整數(shù)。接下來(lái)使用 io.Copy 方法和 os.Stdout 將緩沖區(qū)中的數(shù)據(jù)拷貝到標(biāo)準(zhǔn)輸出中,最后使用 io.ReadAll 方法將緩沖區(qū)中的所有數(shù)據(jù)讀取到一個(gè)字節(jié)切片中,并轉(zhuǎn)換為一個(gè)字符串。
小結(jié)
使用 bytes.Buffer 可以方便高效地處理字節(jié)數(shù)據(jù),避免頻繁地對(duì)底層的字節(jié)數(shù)組進(jìn)行擴(kuò)容和復(fù)制,從而提高性能。