溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

bytes.Buffer怎么在golang中使用

發(fā)布時(shí)間:2021-04-25 14:46:18 來源:億速云 閱讀:739 作者:Leah 欄目:開發(fā)技術(shù)

bytes.Buffer怎么在golang中使用?很多新手對此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

go適合做什么

go是golang的簡稱,而golang可以做服務(wù)器端開發(fā),且golang很適合做日志處理、數(shù)據(jù)打包、虛擬機(jī)處理、數(shù)據(jù)庫代理等工作。在網(wǎng)絡(luò)編程方面,它還廣泛應(yīng)用于web應(yīng)用、API應(yīng)用等領(lǐng)域。

1 bytes.Buffer定義

bytes.Buffer提供可擴(kuò)容的字節(jié)緩沖區(qū),實(shí)質(zhì)是對切片的封裝;結(jié)構(gòu)中包含一個(gè)64字節(jié)的小切片,避免小內(nèi)存分配:

// 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.
}

2 初始化bytes.Buffer的方法

1) var buf bytes.Buffer ->定義一個(gè)空的字節(jié)緩沖區(qū)

2) func NewBuffer(buf []byte) *Buffer { return &Buffer{buf: buf} } -->將字節(jié)切片初始化為緩沖區(qū)

3) func NewBufferString(s string) *Buffer {return &Buffer{buf: []byte(s)}} -->將字符串初始化為緩沖區(qū)

3 提供的主要API函數(shù)

1)寫字節(jié)流數(shù)據(jù)到緩沖區(qū)

// 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
}

2)寫字符串到緩沖區(qū)

// WriteString appends the contents of s to the buffer, growing the buffer as
// needed. The return value n is the length of s; err is always nil. If the
// buffer becomes too large, WriteString will panic with ErrTooLarge.
func (b *Buffer) WriteString(s string) (n int, err error) {
 b.lastRead = opInvalid
 //返回寫入的index
 m := b.grow(len(s))
 return copy(b.buf[m:], s), nil
}

3)從緩沖區(qū)中讀取數(shù)據(jù)

// 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
}

4)從緩沖區(qū)中讀取字符串,直到分隔符delim 位置

// ReadString reads until the first occurrence of delim in the input,
// returning a string containing the data up to and including the delimiter.
// If ReadString encounters an error before finding a delimiter,
// it returns the data read before the error and the error itself (often io.EOF).
// ReadString returns err != nil if and only if the returned data does not end
// in delim.
func (b *Buffer) ReadString(delim byte) (line string, err error) {
 slice, err := b.readSlice(delim)
 return string(slice), err
}

5)將未被讀取的字節(jié)數(shù)據(jù)返回

// Bytes returns a slice of length b.Len() holding the unread portion of the buffer.
// The slice is valid for use only until the next buffer modification (that is,
// only until the next call to a method like Read, Write, Reset, or Truncate).
// The slice aliases the buffer content at least until the next buffer modification,
// so immediate changes to the slice will affect the result of future reads.
func (b *Buffer) Bytes() []byte { return b.buf[b.off:] }

6)將未被讀取的字節(jié)數(shù)據(jù)以字符串形式返回

// String returns the contents of the unread portion of the buffer
// as a string. If the Buffer is a nil pointer, it returns "<nil>".
func (b *Buffer) String() string {
 if b == nil {
  // Special case, useful in debugging.
  return "<nil>"
 }
 return string(b.buf[b.off:])
}

7)返回緩沖區(qū)當(dāng)前容量

// Cap returns the capacity of the buffer's underlying byte slice, that is, the
// total space allocated for the buffer's data.
func (b *Buffer) Cap() int { return cap(b.buf) }

8)返回未被讀取的字節(jié)數(shù)據(jù)大小

// Len returns the number of bytes of the unread portion of the buffer;
// b.Len() == len(b.Bytes()).
func (b *Buffer) Len() int { return len(b.buf) - b.off }

4 bytes.Buffer自動擴(kuò)容機(jī)制

當(dāng)向緩沖區(qū)寫入數(shù)據(jù)時(shí),首先會檢查當(dāng)前容量是否滿足需求,如果不滿足分三種情況處理:

1)當(dāng)前內(nèi)置緩沖區(qū)切片buf為空,且寫入數(shù)據(jù)量小于bootstrap的大?。?4字節(jié)),則bootstrap作為buf

2)當(dāng)前未讀數(shù)據(jù)長度+新寫入數(shù)據(jù)長度小于等于緩沖區(qū)容量的1/2,則挪動數(shù)據(jù)(將未讀的數(shù)據(jù)放到已讀數(shù)據(jù)位置)

3)以上條件不滿足,只能重新分配切片,容量設(shè)定為2*cap(b.buf) + n,即兩倍原來的緩沖區(qū)容量+寫入數(shù)據(jù)量大小

// grow grows the buffer to guarantee space for n more bytes.
// It returns the index where bytes should be written.
// If the buffer can't grow it will panic with ErrTooLarge.
func (b *Buffer) grow(n int) int {
 m := b.Len()
 // If buffer is empty, reset to recover space.
 if m == 0 && b.off != 0 {
  b.Truncate(0)
 }
 //如果需要的容量大于現(xiàn)在的容量--->
 if len(b.buf)+n > cap(b.buf) {
  var buf []byte
  //現(xiàn)有的預(yù)備64byte可以滿足
  if b.buf == nil && n <= len(b.bootstrap) {
   buf = b.bootstrap[0:]
   //實(shí)際需要的小于本身切片容量
  } else if m+n <= cap(b.buf)/2 {
   // We can slide things down instead of allocating a new
   // slice. We only need m+n <= cap(b.buf) to slide, but
   // we instead let capacity get twice as large so we
   // don't spend all our time copying.
   copy(b.buf[:], b.buf[b.off:])
   buf = b.buf[:m]
  } else {
   // not enough space anywhere
   //不夠,那就分配2倍加n的容量
   buf = makeSlice(2*cap(b.buf) + n)
   copy(buf, b.buf[b.off:])
  }
  b.buf = buf
  b.off = 0
 }
 b.buf = b.buf[0 : b.off+m+n]
 return b.off + m
}

5 bytes.Buffer的局限

bytes.Buffer提供了對切片的初步封裝,但也沒做太多的事;對于已讀的數(shù)據(jù)無法操作。

補(bǔ)充:Golang bytes.Buffer 用法精述

1.簡介

bytes.Buffer 是 Golang 標(biāo)準(zhǔn)庫中的緩沖區(qū),具有讀寫方法和可變大小的字節(jié)存儲功能。緩沖區(qū)的零值是一個(gè)待使用的空緩沖區(qū)。

定義如下:

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.
}

注意要點(diǎn):

(1)從 bytes.Buffer 讀取數(shù)據(jù)后,被成功讀取的數(shù)據(jù)仍保留在原緩沖區(qū),只是無法被使用,因?yàn)榫彌_區(qū)的可見數(shù)據(jù)從偏移 off 開始,即buf[off : len(buf)]。

2.常用方法

(1)聲明一個(gè) Buffer

var b bytes.Buffer           //直接定義一個(gè)Buffer變量,不用初始化,可以直接使用
b := new(bytes.Buffer)       //使用New返回Buffer變量
b := bytes.NewBuffer(s []byte)     //從一個(gè)[]byte切片,構(gòu)造一個(gè)Buffer
b := bytes.NewBufferString(s string) //從一個(gè)string變量,構(gòu)造一個(gè)Buffer

(2)往 Buffer 中寫入數(shù)據(jù)

b.Write(d []byte) (n int, err error)      //將切片d寫入Buffer尾部
b.WriteString(s string) (n int, err error)   //將字符串s寫入Buffer尾部
b.WriteByte(c byte) error        //將字符c寫入Buffer尾部
b.WriteRune(r rune) (n int, err error)      //將一個(gè)rune類型的數(shù)據(jù)放到緩沖區(qū)的尾部
b.ReadFrom(r io.Reader) (n int64, err error) //從實(shí)現(xiàn)了io.Reader接口的可讀取對象寫入Buffer尾部

(3)從 Buffer 中讀取數(shù)據(jù)

//讀取 n 個(gè)字節(jié)數(shù)據(jù)并返回,如果 buffer 不足 n 字節(jié),則讀取全部
b.Next(n int) []byte
//一次讀取 len(p) 個(gè) byte 到 p 中,每次讀取新的內(nèi)容將覆蓋p中原來的內(nèi)容。成功返回實(shí)際讀取的字節(jié)數(shù),off 向后偏移 n,buffer 沒有數(shù)據(jù)返回錯(cuò)誤 io.EOF
b.Read(p []byte) (n int, err error)
//讀取第一個(gè)byte并返回,off 向后偏移 n
b.ReadByte() (byte, error)
//讀取第一個(gè) UTF8 編碼的字符并返回該字符和該字符的字節(jié)數(shù),b的第1個(gè)rune被拿掉。如果buffer為空,返回錯(cuò)誤 io.EOF,如果不是UTF8編碼的字符,則消費(fèi)一個(gè)字節(jié),返回 (U+FFFD,1,nil)
b.ReadRune() (r rune, size int, err error)
//讀取緩沖區(qū)第一個(gè)分隔符前面的內(nèi)容以及分隔符并返回,緩沖區(qū)會清空讀取的內(nèi)容。如果沒有發(fā)現(xiàn)分隔符,則返回讀取的內(nèi)容并返回錯(cuò)誤io.EOF
b.ReadBytes(delimiter byte) (line []byte, err error)
//讀取緩沖區(qū)第一個(gè)分隔符前面的內(nèi)容以及分隔符并作為字符串返回,緩沖區(qū)會清空讀取的內(nèi)容。如果沒有發(fā)現(xiàn)分隔符,則返回讀取的內(nèi)容并返回錯(cuò)誤 io.EOF
b.ReadString(delimiter byte) (line string, err error)
//將 Buffer 中的內(nèi)容輸出到實(shí)現(xiàn)了 io.Writer 接口的可寫入對象中,成功返回寫入的字節(jié)數(shù),失敗返回錯(cuò)誤
b.WriteTo(w io.Writer) (n int64, err error)

(4)其它操作

b.Bytes() []byte  //返回字節(jié)切片
b.Cap() int    //返回 buffer 內(nèi)部字節(jié)切片的容量
b.Grow(n int)   //為 buffer 內(nèi)部字節(jié)切片的容量增加 n 字節(jié)
b.Len() int    //返回緩沖區(qū)數(shù)據(jù)長度,等于 len(b.Bytes())
b.Reset()     //清空數(shù)據(jù)
b.String() string  //字符串化
b.Truncate(n int)  //丟棄緩沖區(qū)中除前n個(gè)未讀字節(jié)以外的所有字節(jié)。如果 n 為負(fù)數(shù)或大于緩沖區(qū)長度,則引發(fā) panic
b.UnreadByte() error //將最后一次讀取操作中被成功讀取的字節(jié)設(shè)為未被讀取的狀態(tài),即將已讀取的偏移 off 減 1
b.UnreadRune() error //將最后一次 ReadRune() 讀取操作返回的 UTF8 字符 rune設(shè)為未被讀取的狀態(tài),即將已讀取的偏移 off 減去 字符 rune 的字節(jié)數(shù)

3.使用示例

(1)從文件 test.txt 中讀取全部內(nèi)容追加到 buffer 尾部

test.txt 的內(nèi)容為:

My name is dablelv

具體實(shí)現(xiàn):

package main
import (
 "os"
 "fmt"
 "bytes"
)
func main() {
    file, _ := os.Open("./test.txt")    
    buf := bytes.NewBufferString("Hello world ")    
    buf.ReadFrom(file)              //將text.txt內(nèi)容追加到緩沖器的尾部    
    fmt.Println(buf.String())
}

編譯運(yùn)行輸出:

Hello world My name is dablelv

看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進(jìn)一步的了解或閱讀更多相關(guān)文章,請關(guān)注億速云行業(yè)資訊頻道,感謝您對億速云的支持。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI