go基础——buffer

2020-10-05  本文已影响0人  chase_lwf

内容

1 bytes.Buffer
2 strings.Builder
3 bufio包

前言
bytes.Buffer strings.Builder和bufio都是golang中经常使用的提供了缓冲池的数据结构,他们内部都是封装了一个[]byte, 可以用来高效的操作字节切片、字符串和io操作

一 byte.Buffer

byte.Buffer是一个简单字节缓冲池,内部包了一个字节数组,在某些频繁io的操作中,可以使用buffer来做一个读取或是写入的缓冲池,来提高效率

// 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)]
    lastRead readOp // last read operation, so that Unread* can work correctly.
}

二 strings.builder

strings.builder可以高效的写入、拼接字符串,其内部封装了一个字节数组,写入时其实是将传入的字节append到内部的字节数组上

// A Builder is used to efficiently build a string using Write methods.
// It minimizes memory copying. The zero value is ready to use.
// Do not copy a non-zero Builder.
type Builder struct {
    addr *Builder // of receiver, to detect copies by value
    buf  []byte
}

// Write appends the contents of p to b's buffer.
// Write always returns len(p), nil.
func (b *Builder) Write(p []byte) (int, error) {
    b.copyCheck()
    b.buf = append(b.buf, p...)
    return len(p), nil
}
    builder := strings.Builder{}
    builder.WriteString("haha")
    builder2 := builder
    builder2.WriteString("ww")

builder2.WriteString会调用copyCheck检查内部切片是否为nil,不为nil直接panic

func (b *Builder) copyCheck() {
    if b.addr == nil {
        // This hack works around a failing of Go's escape analysis
        // that was causing b to escape and be heap allocated.
        // See issue 23382.
        // TODO: once issue 7921 is fixed, this should be reverted to
        // just "b.addr = b".
        b.addr = (*Builder)(noescape(unsafe.Pointer(b)))
    } else if b.addr != b {
        panic("strings: illegal use of non-zero Builder copied by value")
    }
}

三 bufio

bufio包提供了有缓冲的io,它定义了两个结构体,分别是Reader和Writer, 它们也分别实现了io包中io.Reader和io.Writer接口, 通过传入一个io.Reader的实现对象和一个缓冲池大小参数,可以构造一个bufio.Reader对象,根据bufio.Reader的相关方法便可读取io.Reader中数据流,因为带有缓冲池,读数据会先读到缓冲池,再次读取会先去缓冲池读取,这样减少了io操作,提高了效率;

// 构造Reader对象
func NewReaderSize(rd io.Reader, size int) *Reader {}

// Reader implements buffering for an io.Reader object.
type Reader struct {
    buf          []byte
    rd           io.Reader // reader provided by the client
    r, w         int       // buf read and write positions
    err          error
    lastByte     int // last byte read for UnreadByte; -1 means invalid
    lastRuneSize int // size of last rune read for UnreadRune; -1 means invalid
}

// Writer implements buffering for an io.Writer object.
type Writer struct {
    err error
    buf []byte
    n   int
    wr  io.Writer
}

func (b *Reader) Read(p []byte) (n int, err error) 具体读取流程如下:

func (b *Writer) Write(p []byte) (nn int, err error) 具体写入流程如下:

引用:

上一篇 下一篇

猜你喜欢

热点阅读