golang源碼 bytes/buffer.go閱讀

這裏是個人語雀 www.yuque.com/absbootstrap

buffer.go

Overview

這是 bytes 包裏的 buffer 實現 app

一圖勝千言

看不懂圖的再看下面吧
函數

buffer.jpg

核心函數

Buffer 結構

這是 buffer 的內部結構
buf 字節切片,用來存儲 buffer 的內容
off 是表明從哪裏開始讀
bootstrap 用來做爲字節切片太小的時候防止屢次申請空間減少開銷
lastRead 用來記錄上一次的操做學習

// 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.
// 注意 buffer 的零值是空的 buf
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.

	// FIXME: it would be advisable to align Buffer to cachelines to avoid false
	// sharing.
}

複製代碼

Grow(n int)

申請擴展緩衝區優化

// Grow grows the buffer's capacity, if necessary, to guarantee space for
// another n bytes. After Grow(n), at least n bytes can be written to the
// buffer without another allocation.
// If n is negative, Grow will panic.
// If the buffer can't grow it will panic with ErrTooLarge.
// 增長容量 n byte
func (b *Buffer) Grow(n int) {
	if n < 0 {
		panic("bytes.Buffer.Grow: negative count")
	}
	m := b.grow(n)
	b.buf = b.buf[:m]
}
複製代碼

WriteString(s string) (n int, err error)

向 buffer 中寫字符串ui

// 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.
// 直接寫 string 也行,同時自動擴展
func (b *Buffer) WriteString(s string) (n int, err error) {
	b.lastRead = opInvalid
	//先嚐試不用擴展容量的寫法
	m, ok := b.tryGrowByReslice(len(s))
	if !ok {
		m = b.grow(len(s))
	}
	// copy 能夠直接把 string 類型做爲 字節切片拷貝過去
	return copy(b.buf[m:], s), nil
}

複製代碼

也有寫字節切片的形式  Write(p []byte) (n int, err error)this

ReadFrom(r io.Reader) (n int64, err error)

從 io.Reader 讀取數據到 buffer 中spa

// ReadFrom reads data from r until EOF and appends it to the buffer, growing
// the buffer as needed. The return value n is the number of bytes read. Any
// error except io.EOF encountered during the read is also returned. If the
// buffer becomes too large, ReadFrom will panic with ErrTooLarge.
// 從實現了 io.Reader 接口的 r 中讀取到 EOF 爲止,若是超出了 maxInt 那麼大就會返回太
// 大不能經過一個 [maxInt]byte 字節切片來存儲了
func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) {
	b.lastRead = opInvalid
	for {
		i := b.grow(MinRead)
		// grow 申請了 n 個空間以後,會將 buffer 中的字節切片延長長度到 n 個字節以後
		// 因此須要從新賦值一下長度,避免一些誤解,保證長度都是有效數據提供的
		b.buf = b.buf[:i]
		// 將 r 中的數據讀到 buffer 中去
		m, e := r.Read(b.buf[i:cap(b.buf)])
		if m < 0 {
			panic(errNegativeRead)
		}

		// 手動更改長度
		b.buf = b.buf[:i+m]
		n += int64(m)
		if e == io.EOF {
			return n, nil // e is EOF, so return nil explicitly
		}
		if e != nil {
			return n, e
		}
	}
}
複製代碼

WriteTo(w io.Writer) (n int64, err error)

向 io.Writer 中寫數據指針

// WriteTo writes data to w until the buffer is drained or an error occurs.
// The return value n is the number of bytes written; it always fits into an
// int, but it is int64 to match the io.WriterTo interface. Any error
// encountered during the write is also returned.
func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) {
	b.lastRead = opInvalid
	if nBytes := b.Len(); nBytes > 0 {
		//從 off 開始讀的地方算起,所有寫到 io.Writer 中去
		m, e := w.Write(b.buf[b.off:])
		//寫的多了就報錯
		if m > nBytes {
			panic("bytes.Buffer.WriteTo: invalid Write count")
		}
		//記錄寫過了多少,位移 offset 指針
		b.off += m

		n = int64(m)
		if e != nil {
			return n, e
		}
		// all bytes should have been written, by definition of
		// Write method in io.Writer
		// 由於剛纔判斷過寫多了的狀況,因此這裏是寫少了
		if m != nBytes {
			return n, io.ErrShortWrite
		}
	}
	// Buffer is now empty; reset.
	// 寫完以後重置
	b.Reset()
	return n, nil
}
複製代碼

ReadBytes(delim byte) (line []byte, err error)

用來讀到終止符就結束,返回的是一個 line 字節切片包含終止符前的數據code

// ReadBytes reads until the first occurrence of delim in the input,
// returning a slice containing the data up to and including the delimiter.
// If ReadBytes encounters an error before finding a delimiter,
// it returns the data read before the error and the error itself (often io.EOF).
// ReadBytes returns err != nil if and only if the returned data does not end in
// delim.
// 讀取到終止符爲止,就結束
func (b *Buffer) ReadBytes(delim byte) (line []byte, err error) {
	slice, err := b.readSlice(delim)
	// return a copy of slice. The buffer's backing array may
	// be overwritten by later calls.
	line = append(line, slice...)
	return line, err
}

複製代碼

NewBuffer(buf []byte) *Buffer

用來新建一個新的 Buffer ,其實也可使用 new 和 var 來聲明

// NewBuffer creates and initializes a new Buffer using buf as its
// initial contents. The new Buffer takes ownership of buf, and the
// caller should not use buf after this call. NewBuffer is intended to
// prepare a Buffer to read existing data. It can also be used to size
// the internal buffer for writing. To do that, buf should have the
// desired capacity but a length of zero.
//
// In most cases, new(Buffer) (or just declaring a Buffer variable) is
// sufficient to initialize a Buffer.
// 經過字節切片建立一個 buffer ,字節切片會保留初始值
// 在渴望容量可是長度爲 0?的狀況下
// 也能夠看成內核的 buffer 來寫入
func NewBuffer(buf []byte) *Buffer { return &Buffer{buf: buf} }
複製代碼

同時也有經過 string 類型的實現
**func NewBufferString(s string) *Buffer {return &Buffer{buf: []byte(s)}}**

總結

緩衝區,實現了大小控制,字節切片和 string 類型的讀寫,同時還對狀況進行了優化,好比存在 bootstrap,好比 grow 函數中的屢次檢定。適合多讀精讀來學習

相關文章
相關標籤/搜索