go bytes — byte slice 便利操作


原文鏈接

bytes — byte slice 便利操作

該包定義了一些操作 byte slice 的便利操作。因為字符串可以表示為 []byte,因此,bytes 包定義的函數、方法等和 strings 包很類似,所以講解時會和 strings 包類似甚至可以直接參考。

說明:為了方便,會稱呼 []byte 為 字節數組

byte類型

是否存在某個子 slice

// 子 slice subslice 在 b 中,返回 true
func Contains(b, subslice []byte) bool
該函數的內部調用了 bytes.Index 函數(在后面會講解):

    func Contains(b, subslice []byte) bool {
        return Index(b, subslice) != -1
    }

題外:對比 strings.Contains 你會發現,一個判斷 >=0,一個判斷 != -1,可見庫不是一個人寫的,沒有做到一致性。

[]byte 出現次數

// slice sep 在 s 中出現的次數(無重疊)
func Count(s, sep []byte) int

和 strings 實現不同,此包中的 Count 核心代碼如下:

count := 0
c := sep[0]
i := 0
t := s[:len(s)-n+1]
for i < len(t) {
    // 判斷 sep 第一個字節是否在 t[i:] 中
    // 如果在,則比較之后相應的字節
    if t[i] != c {
        o := IndexByte(t[i:], c)
        if o < 0 {
            break
        }
        i += o
    }
    // 執行到這里表示 sep[0] == t[i]
    if n == 1 || Equal(s[i:i+n], sep) {
        count++
        i += n
        continue
    }
    i++
}

Runes 類型轉換

// 將 []byte 轉換為 []rune
func Runes(s []byte) []rune
該函數將 []byte 轉換為 []rune ,適用於漢字等多字節字符,示例:

b:=[]byte("你好,世界")
for k,v:=range b{
    fmt.Printf("%d:%s |",k,string(v))
}
r:=bytes.Runes(b)
for k,v:=range r{
    fmt.Printf("%d:%s|",k,string(v))
}
運行結果:

0:ä |1:½ |2:  |3:å |4:¥ |5:½ |6:ï |7:¼ |8:  |9:ä |10:¸ |11:  |12:ç |13:  |14: |
0:你|1:好|2:,|3:世|4:界|

Reader 類型

type Reader struct {
    s        []byte
    i        int64 // 當前讀取下標
    prevRune int   // 前一個字符的下標,也可能 < 0
}

bytes 包下的 Reader 類型實現了 io 包下的 Reader, ReaderAt, RuneReader, RuneScanner, ByteReader, ByteScanner, ReadSeeker, Seeker, WriterTo 等多個接口。主要用於 Read 數據。

我們需要在通過 bytes.NewReader 方法來初始化 bytes.Reader 類型的對象。初始化時傳入 []byte 類型的數據。NewReader 函數簽名如下:

func NewReader(b []byte) *Reader

如果直接聲明該對象了,可以通過 Reset 方法重新寫入數據,示例:

x:=[]byte("你好,世界")

r1:=bytes.NewReader(x)
d1:=make([]byte,len(x))
n,_:=r1.Read(d1)
fmt.Println(n,string(d1))

r2:=bytes.Reader{}
r2.Reset(x)
d2:=make([]byte,len(x))
n,_=r2.Read(d2)
fmt.Println(n,string(d2))

輸出結果:

15 你好,世界
15 你好,世界

Reader 包含了 8 個讀取相關的方法,實現了前面提到的 io 包下的 9 個接口(ReadSeeker 接口內嵌 Reader 和 Seeker 兩個接口):

// 讀取數據至 b 
func (r *Reader) Read(b []byte) (n int, err error) 
// 讀取一個字節
func (r *Reader) ReadByte() (byte, error)
// 讀取一個字符
func (r *Reader) ReadRune() (ch rune, size int, err error)
// 讀取數據至 w
func (r *Reader) WriteTo(w io.Writer) (n int64, err error)
// 進度下標指向前一個字節,如果 r.i <= 0 返回錯誤。
func (r *Reader) UnreadByte() 
// 進度下標指向前一個字符,如果 r.i <= 0 返回錯誤,且只能在每次 ReadRune 方法后使用一次,否則返回錯誤。
func (r *Reader) UnreadRune() 
// 讀取 r.s[off:] 的數據至b,該方法忽略進度下標 i,不使用也不修改。
func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) 
// 根據 whence 的值,修改並返回進度下標 i ,當 whence == 0 ,進度下標修改為 off,當 whence == 1 ,進度下標修改為 i+off,當 whence == 2 ,進度下標修改為 len[s]+off.
// off 可以為負數,whence 的只能為 0,1,2,當 whence 為其他值或計算后的進度下標越界,則返回錯誤。
func (r *Reader) Seek(offset int64, whence int) (int64, error)

示例:

x := []byte("你好,世界")
r1 := bytes.NewReader(x)

ch, size, _ := r1.ReadRune()
fmt.Println(size, string(ch))
_ = r1.UnreadRune()
ch, size, _ = r1.ReadRune()
fmt.Println(size, string(ch))
_ = r1.UnreadRune()

by, _ := r1.ReadByte()
fmt.Println(by)
_ = r1.UnreadByte()
by, _ = r1.ReadByte()
fmt.Println(by)
_ = r1.UnreadByte()

d1 := make([]byte, 6)
n, _ := r1.Read(d1)
fmt.Println(n, string(d1))

d2 := make([]byte, 6)
n, _ = r1.ReadAt(d2, 0)
fmt.Println(n, string(d2))

w1 := &bytes.Buffer{}
_, _ = r1.Seek(0, 0)
_, _ = r1.WriteTo(w1)
fmt.Println(w1.String())

運行結果:

3 你 3 你 228 228 6 你好 6 你好 你好,世界 

Buffer 類型

type Buffer struct {
    buf      []byte
    off      int   
    lastRead readOp 
}

在上一個示例的最后,我們使用了 bytes.Buffer 類型,該類型實現了 io 包下的 ByteScanner, ByteWriter, ReadWriter, Reader, ReaderFrom, RuneReader, RuneScanner, StringWriter, Writer, WriterTo 等接口,可以方便的進行讀寫操作。

對象可讀取數據為 buf[off : len(buf)], off 表示進度下標,lastRead 表示最后讀取的一個字符所占字節數,方便 Unread* 相關操作。

Buffer 可以通過 3 中方法初始化對象:

a := bytes.NewBufferString("Hello World")
b := bytes.NewBuffer([]byte("Hello World"))
c := bytes.Buffer{}

fmt.Println(a)
fmt.Println(b)
fmt.Println(c)
}

輸出結果:

Hello World
Hello World
{[] 0 0} 

Buffer 包含了 21 個讀寫相關的方法,大部分同名方法的用法與前面講的類似,這里只講演示其中的 3 個方法:

// 讀取到字節 delim 后,以字節數組的形式返回該字節及前面讀取到的字節。如果遍歷 b.buf 也找不到匹配的字節,則返回錯誤(一般是 EOF)
func (b *Buffer) ReadBytes(delim byte) (line []byte, err error)
// 讀取到字節 delim 后,以字符串的形式返回該字節及前面讀取到的字節。如果遍歷 b.buf 也找不到匹配的字節,則返回錯誤(一般是 EOF)
func (b *Buffer) ReadString(delim byte) (line string, err error)
// 截斷 b.buf , 舍棄 b.off+n 之后的數據。n == 0 時,調用 Reset 方法重置該對象,當 n 越界時(n < 0 || n > b.Len() )方法會觸發 panic.
func (b *Buffer) Truncate(n int)

示例:

a := bytes.NewBufferString("Good Night")

x, err := a.ReadBytes('t')
if err != nil {
    fmt.Println("delim:t err:", err)
} else {
    fmt.Println(string(x))
}

a.Truncate(0)
a.WriteString("Good Night")
fmt.Println(a.Len())
a.Truncate(5)
fmt.Println(a.Len())
y, err := a.ReadString('N')
if err != nil {
    fmt.Println("delim:N err:", err)
} else {
    fmt.Println(y)
}

輸出結果:

Good Night
10
5
delim:N err: EOF

其它函數

其它大部分函數、方法與 strings 包下的函數、方法類似,只是數據源從 string 變為了 []byte ,請參考 strings 包的用法。

 

原文鏈接

type Buffer

緩沖區是一個可變大小的帶有讀和寫方法的字節緩沖區。Buffer 的零值是一個准備使用的空緩沖區。

func NewBuffer
func NewBuffer(buf []byte) *Buffer
NewBuffer 使用 buf 作為其初始內容創建並初始化新的 Buffer。新的緩沖區取得了 buf 的所有權,並且調用者在調用之后不應該使用 buf 。NewBuffer 旨在准備一個緩沖區來讀取現有數據。它也可以用來調整寫入的內部緩沖區大小。要做到這一點,buf 應該具有所需的容量,但長度為零。
在大多數情況下,新的(緩沖區)(或者只是聲明一個緩沖區變量)足以初始化緩沖區。

func NewBufferString
func NewBufferString(s string) *Buffer
NewBufferString 使用字符串 s 作為其初始內容創建並初始化一個新的 Buffer。它旨在准備一個緩沖區來讀取現有的字符串。


func (*Buffer) Bytes
func (b *Buffer) Bytes() []byte
字節返回一段長度 b.Len(),其中包含緩沖區的未讀部分。該切片僅在下一次緩沖區修改之前有效(即,直到下一次調用 Read,Write,Reset或Truncate 之類的方法)。至少在下一次緩沖區修改之前,切片會對緩沖區內容進行別名,因此切片的即時更改將影響將來讀取的結果。

func (*Buffer) Cap
func (b *Buffer) Cap() int
Cap 返回緩沖區底層字節片段的容量,即分配給緩沖區數據的總空間。

func (*Buffer) Grow
func (b *Buffer) Grow(n int)
如果有必要,增長緩沖區的容量以保證另外n個字節的空間。在Grow(n)之后,至少可以將n個字節寫入緩沖區而無需其他分配。如果n是負數,Grow 會陷入混亂。如果緩沖區不能增長,它會與 ErrTooLarge 一起發生混亂。

func (*Buffer) Len
func (b *Buffer) Len() int
Len 返回緩沖區未讀部分的字節數;b.Len() == len(b.Bytes())。

func (*Buffer) Next
func (b *Buffer) Next(n int) []byte
接下來返回包含來自緩沖區的下n個字節的切片,如同字節已由 Read 返回一樣推進緩沖區。如果緩沖區中少於n個字節,則 Next 返回整個緩沖區。切片只有在下次調用讀取或寫入方法時才有效。

func (*Buffer) Read
func (b *Buffer) Read(p []byte) (n int, err error)
Read 從緩沖區中讀取下一個 len(p) 字節,或者直到緩沖區被耗盡。返回值n是讀取的字節數。如果緩沖區沒有數據要返回,則 err 為 io.EOF(除非len(p)為零); 否則為零。

func (*Buffer) ReadByte
func (b *Buffer) ReadByte() (byte, error)
ReadByte 讀取並返回緩沖區中的下一個字節。如果沒有可用的字節,則返回錯誤 io.EOF。

func (*Buffer) ReadBytes
func (b *Buffer) ReadBytes(delim byte) (line []byte, err error)
ReadBytes 一直讀取,直到輸入中delim第一次出現時停止 ,並返回一個包含小於等於分隔符數據的片段。如果ReadBytes在查找分隔符之前遇到錯誤,它將返回錯誤之前讀取的數據和錯誤本身(通常為 io.EOF )。當且僅當返回的數據不以分隔符結束時,ReadBytes 才返回 err != nil。

func (*Buffer) ReadFrom
func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error)
ReadFrom 從 r 讀取數據直到 EOF 並將其附加到緩沖區,根據需要生長緩沖區。返回值n是讀取的字節數。讀取過程中遇到的除 io.EOF 外的任何錯誤也會返回。如果緩沖區變得過大,ReadFrom 將與 ErrTooLarge 一起發生混亂。

func (*Buffer) ReadRune
func (b *Buffer) ReadRune() (r rune, size int, err error)
ReadRune 讀取並返回緩沖區中的下一個UTF-8編碼的 Unicode 代碼點。如果沒有字節可用,返回的錯誤是io.EOF。如果字節是錯誤的UTF-8編碼,則它將消耗一個字節並返回U + FFFD,1。

func (*Buffer) ReadString
func (b *Buffer) ReadString(delim byte) (line string, err error)
ReadString 讀取,直到輸入中第一次出現 delim ,返回一個包含數據的字符串直到並包含分隔符。如果ReadString 在查找分隔符之前遇到錯誤,它將返回在錯誤之前讀取的數據和錯誤本身(通常為 io.EOF )。當且僅當返回的數據沒有以分隔符結束時,ReadString 返回 err!= nil。

func (*Buffer) Reset
func (b *Buffer) Reset()
Reset將緩沖區重置為空,但它保留了未來寫入使用的底層存儲。重置與Truncate(0) 相同。

func (*Buffer) String
func (b *Buffer) String() string
字符串以字符串形式返回緩沖區未讀部分的內容。如果 Buffer 是一個零指針,它將返回“<nil>”。

func (*Buffer) Truncate
func (b *Buffer) Truncate(n int)
截斷從緩沖區丟棄除前 n 個未讀字節以外的所有字節,但繼續使用相同的分配存儲。如果 n 是負數或大於緩沖區的長度,它會發生混亂。

func (*Buffer) UnreadByte
func (b *Buffer) UnreadByte() error
UnreadByte 讀取最近成功讀取操作返回的最后一個字節,該操作至少讀取一個字節。如果自上次讀取后發生寫入,如果上次讀取返回錯誤,或者讀取讀取的是零字節,則 UnreadByte 返回錯誤。

func (*Buffer) UnreadRune
func (b *Buffer) UnreadRune() error
UnreadRune 未讀取 ReadRune 返回的最后一個符文。如果緩沖區上的最新讀取或寫入操作不是成功的ReadRune,則 UnreadRune 將返回錯誤。(在這方面,它比 UnreadByte 更嚴格,它將讀取任何讀操作的最后一個字節。)

func (*Buffer) Write
func (b *Buffer) Write(p []byte) (n int, err error)
寫入將 p 的內容附加到緩沖區,根據需要增加緩沖區。返回值n是 p 的長度; err 總是零。如果緩沖區變得過大,Write 會與 ErrTooLarge 混淆。

func (*Buffer) WriteByte
func (b *Buffer) WriteByte(c byte) error
WriteByte 將字節 c 附加到緩沖區,根據需要生長緩沖區。返回的錯誤始終為零,但包含在內以匹配
bufio.Writer 的 WriteByte 。如果緩沖區變得太大,WriteByte 會與 ErrTooLarge 一起發生混亂。

func (*Buffer) WriteRune
func (b *Buffer) WriteRune(r rune) (n int, err error)
WriteRune 將 Unicode 代碼點 r 的UTF-8 編碼附加到緩沖區,返回其長度和錯誤,該錯誤總是為零,但包含在內以匹配 bufio.Writer 的 WriteRune。緩沖區根據需要增長;如果它變得太大,WriteRune 將會與 ErrTooLarge 混淆。

func (*Buffer) WriteString
func (b *Buffer) WriteString(s string) (n int, err error)
WriteString將 s 的內容附加到緩沖區,根據需要增加緩沖區。返回值 n 是 s 的長度;err 總是零。如果緩沖區變得太大,WriteString 會與 ErrTooLarge 混淆。

func (*Buffer) WriteTo
func (b *Buffer) WriteTo(w io.Writer) (n int64, err error)
WriteTo 將數據寫入 w 直到緩沖區耗盡或發生錯誤。返回值n是寫入的字節數;它總是適合 int ,但它是
int64 來匹配 io.WriterTo 接口。寫入過程中遇到的任何錯誤也會返回。

 

type Reader

Reader 通過從字節片段讀取來實現 io.Reader,io.ReaderAt,io.WriterTo,io.Seeker,io.ByteScanner和io.RuneScanner 接口。與緩沖區不同,Reader 是只讀的並支持搜索。

type Reader struct {
// 包含過濾或未導出的字段
}

func NewReader
func NewReader(b []byte) *Reader
NewReader從 b 返回新的 Reader 讀數。

func (*Reader) Len
func (r *Reader) Len() int
Len 返回切片的未讀部分的字節數。

func (*Reader) Read
func (r *Reader) Read(b []byte) (n int, err error)

func (*Reader) ReadAt
func (r *Reader) ReadAt(b []byte, off int64) (n int, err error)

func (*Reader) ReadByte
func (r *Reader) ReadByte() (byte, error
)
func (*Reader) ReadRune
func (r *Reader) ReadRune() (ch rune, size int, err error)

func (*Reader) Reset
func (r *Reader) Reset(b []byte)
Reset 將Reader(讀取器)重置為從 b 中讀取。

func (*Reader) Seek
func (r *Reader) Seek(offset int64, whence int) (int64, error)
Seek 實現了 io.Seeker 接口。

func (*Reader) Size
func (r *Reader) Size() int64
Size 返回基礎字節片的原始長度。大小是可通過 ReadAt 讀取的字節數。返回的值總是相同的,不受調用任何其他方法的影響。

func (*Reader) UnreadByte
func (r *Reader) UnreadByte() error

func (*Reader) UnreadRune
func (r *Reader) UnreadRune() error

func (*Reader) WriteTo
func (r *Reader) WriteTo(w io.Writer) (n int64, err error)
WriteTo 實現 io.WriterTo 接口。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM