Go source code learning: bufio package-1.1-bufio.go-(4)

bufio package official documentation

Go source code learning-index directory

Previous article on bufio package learning: Go source code learning: bufio package-1.1-bufio.go-(3)

27. WriteByte: Write a single byte

This part of the code defines WriteBytethe method for writing a single byte to the buffer.

// WriteByte 写入单个字节。
func (b *Writer) WriteByte(c byte) error {
    
    
    // 如果存在错误,直接返回错误。
    if b.err != nil {
    
    
        return b.err
    }
    // 如果可用空间不足且刷新操作失败,返回错误。
    if b.Available() <= 0 && b.Flush() != nil {
    
    
        return b.err
    }
    // 将字节 c 写入缓冲区,并更新写指针 b.n。
    b.buf[b.n] = c
    b.n++
    return nil
}

explain:

  • WriteByteThe method is Writera method of the structure, and the receiver is Writera pointer to the structure b.
  • First, check if there is an error, and if so, return an error directly.
  • Then, check whether the available space of the buffer is sufficient, and whether the flush operation is successful, and return an error if it is unsuccessful.
  • Finally, cthe single byte represented by the parameter is written to the buffer and the write pointer is updated b.n.

effect:

  • WriteByteThe method is used to write a single byte to the buffer, often used to write data by bytes.
  • Before writing, error checks are performed, including whether there is enough buffer space and whether the flush operation was successful.
  • After the write operation is successful, the write pointer is updated and prepared to write the next byte.

28. WriteRune: Write a single Unicode code point

This part of the code defines WriteRunemethods for writing a single Unicode code point, returning the number of bytes written and any errors.

// WriteRune 写入单个Unicode码点,返回写入的字节数和任何错误。
func (b *Writer) WriteRune(r rune) (size int, err error) {
    
    
    // 以uint32比较以正确处理负数的rune。
    if uint32(r) < utf8.RuneSelf {
    
    
        // 如果rune可以用一个字节表示,调用WriteByte写入。
        err = b.WriteByte(byte(r))
        if err != nil {
    
    
            return 0, err
        }
        return 1, nil
    }
    // 如果存在错误,直接返回错误。
    if b.err != nil {
    
    
        return 0, b.err
    }
    // 获取可用空间。
    n := b.Available()
    // 如果可用空间小于utf8.UTFMax,执行刷新操作。
    if n < utf8.UTFMax {
    
    
        if b.Flush(); b.err != nil {
    
    
            return 0, b.err
        }
        // 再次获取可用空间,如果仍然小于utf8.UTFMax,调用WriteString写入。
        n = b.Available()
        if n < utf8.UTFMax {
    
    
            // 只有在缓冲区非常小的情况下才会发生。
            return b.WriteString(string(r))
        }
    }
    // 使用utf8.EncodeRune将rune编码为字节序列,更新写指针。
    size = utf8.EncodeRune(b.buf[b.n:], r)
    b.n += size
    return size, nil
}

explain:

  • WriteRuneThe method is Writera method of the structure, and the receiver is Writera pointer to the structure b.
  • rFirst, it checks whether the Unicode code point can be represented by a byte, and if so, calls WriteBytethe method to write directly.
  • Then, check if there is an error and return an error directly if there is one.
  • Get the buffer's available space n.
  • If the available space is less than that utf8.UTFMax, perform a refresh operation.
  • Get the free space again, and if it's still less than that utf8.UTFMax, call WriteStringthe method to write the Unicode code point as a string.
  • Finally, use utf8.EncodeRuneEncode the Unicode code point into a sequence of bytes, updating the write pointer.

effect:

  • WriteRuneMethod is used to write a single Unicode code point to the buffer and can handle multi-byte Unicode code points.
  • Before writing, a series of checks and operations are performed, including determining whether it can be represented by one byte, flushing the buffer, and utf8.EncodeRuneencoding using .
  • Returns the number of bytes written and any errors.

29. WriteString: Write a string

This part of the code defines WriteStringmethods for writing strings. It returns the number of bytes written and possible error information.

// WriteString 写入字符串。
// 返回写入的字节数。
// 如果字节数小于 len(s),还返回一个解释写入为何不完整的错误。
func (b *Writer) WriteString(s string) (int, error) {
    
    
    var sw io.StringWriter
    tryStringWriter := true

    nn := 0
    for len(s) > b.Available() && b.err == nil {
    
    
        var n int
        if b.Buffered() == 0 && sw == nil && tryStringWriter {
    
    
            // 仅检查一次 b.wr 是否为 StringWriter。
            sw, tryStringWriter = b.wr.(io.StringWriter)
        }
        if b.Buffered() == 0 && tryStringWriter {
    
    
            // 大写入、空缓冲区,底层写入器支持 WriteString:
            // 将写入转发到底层 StringWriter。
            // 这避免了额外的复制。
            n, b.err = sw.WriteString(s)
        } else {
    
    
            n = copy(b.buf[b.n:], s)
            b.n += n
            b.Flush()
        }
        nn += n
        s = s[n:]
    }
    if b.err != nil {
    
    
        return nn, b.err
    }
    n := copy(b.buf[b.n:], s)
    b.n += n
    nn += n
    return nn, nil
}

explain:

  • WriteStringThe method is Writera method of the structure, and the receiver is Writera pointer to the structure b.
  • Inside the method, the string is processed in a loop suntil all is written or an error occurs.
  • On each iteration, it is checked that the remaining space is enough to hold the current string and that no errors occurred.
  • If the buffer is empty and the underlying writer b.wris StringWriteran implementation of the interface, an attempt is made to delegate the write operation directly to the underlying writer StringWriter.
  • If the buffer is not empty, or cannot be delegated to StringWriter, the string is written to the buffer using conventional copy( copy) methods, flushing if necessary.
  • Accumulate the number of bytes written nnand update the string s.
  • Finally, if there is an error, the cumulative number of bytes and the error are returned; otherwise, the cumulative sum of the number of bytes is returned nil.

effect:

  • WriteStringThe method is used to write a string into a buffer, handling the situation where the buffer size is not large enough to accommodate the entire string.
  • Before writing, it will try to delegate the writing operation to the underlying StringWriterinterface to improve efficiency.
  • Returns the number of bytes written and possible error information.

30. ReadFrom: Read data from the reader

This part of the code defines ReadFrommethods for implementing io.ReaderFromthe interface. If the underlying writer supports ReadFromthe method, this method will call the underlying ReadFrommethod. If buffered data and underlying support are present ReadFrom, ReadFromthe buffer is filled and data is written before calling .

// ReadFrom 实现了 [io.ReaderFrom] 接口。如果底层写入器
// 支持 ReadFrom 方法,此方法将调用底层的 ReadFrom。
// 如果存在缓冲数据和底层支持 ReadFrom,此方法在调用 ReadFrom 之前
// 填充缓冲区并写入数据。
func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) {
    
    
    if b.err != nil {
    
    
        return 0, b.err
    }
    readerFrom, readerFromOK := b.wr.(io.ReaderFrom)
    var m int
    for {
    
    
        if b.Available() == 0 {
    
    
            if err1 := b.Flush(); err1 != nil {
    
    
                return n, err1
            }
        }
        if readerFromOK && b.Buffered() == 0 {
    
    
            nn, err := readerFrom.ReadFrom(r)
            b.err = err
            n += nn
            return n, err
        }
        nr := 0
        for nr < maxConsecutiveEmptyReads {
    
    
            m, err = r.Read(b.buf[b.n:])
            if m != 0 || err != nil {
    
    
                break
            }
            nr++
        }
        if nr == maxConsecutiveEmptyReads {
    
    
            return n, io.ErrNoProgress
        }
        b.n += m
        n += int64(m)
        if err != nil {
    
    
            break
        }
    }
    if err == io.EOF {
    
    
        // 如果刚好填满缓冲区,则预先刷新。
        if b.Available() == 0 {
    
    
            err = b.Flush()
        } else {
    
    
            err = nil
        }
    }
    return n, err
}

explain:

  • ReadFromThe method is Writera method of the structure, and the receiver is Writera pointer to the structure b.
  • Inside the method, first check if there is an error, and if so, return zero bytes and the error directly.
  • Then, check whether the underlying writer b.wrimplements io.ReaderFromthe interface and whether there is underlying support ReadFrom.
  • In the loop, if the buffer free space is zero, first try to flush the buffer to ensure there is enough space for writing data.
  • If the underlying layer supports ReadFromand the buffer is empty, call the underlying ReadFrommethod directly to write the reader r's data to the underlying writer and return the number of bytes read and an error.
  • If the underlying layer does not support it ReadFromor the buffer is not empty, the data is read from the reader rto the buffer in a loop until the maximum number of consecutive empty reads is reached.
  • The amount of data read is accumulated into the total number of bytes n, and the write pointer of the buffer is updated at the same time b.n.
  • If an error occurs, exit the loop.
  • Finally, if the error is io.EOF, flush early if the buffer is just full to ensure all data is written.

effect:

  • ReadFromMethod used to read data from a reader rand write it to the underlying writer.
  • If the underlying layer supports it , efficient data transmission is achieved ReadFromby calling the underlying method.ReadFrom
  • At the same time, the status of the buffer is taken into account to ensure that there is enough space for writing data.

31. ReadWriter: buffered input and output

This part of the code defines ReadWritera structure, which contains pointers to Readerand Writer, and implements io.ReadWriterthe interface.

// buffered input and output

// ReadWriter 存储指向 [Reader] 和 [Writer] 的指针。
// 它实现了 [io.ReadWriter] 接口。
type ReadWriter struct {
    
    
    *Reader
    *Writer
}

// NewReadWriter 分配一个新的 [ReadWriter],将其分派给 r 和 w。
func NewReadWriter(r *Reader, w *Writer) *ReadWriter {
    
    
    return &ReadWriter{
    
    r, w}
}

explain:

  • ReadWriterIs a structure containing two pointer members: Readerand Writer. These two pointers point to Readerstructure and Writerstructure respectively.
  • The structure implements io.ReadWriterthe interface, which means it can be read and written simultaneously.
  • NewReadWriterThe function is used to allocate and return a new one ReadWriter. The function receives a Readerand a Writerand assigns them respectively to ReadWriterthe members of the structure.

effect:

  • ReadWriterStructures are designed to provide buffered input and output capabilities, allowing reading and writing operations to them.
  • By combining Readerand Writertogether, the ability to read and write simultaneously is achieved.
  • NewReadWriterThe function creates a new ReadWriterinstance and associates the given Readerand Writerto the instance.

Guess you like

Origin blog.csdn.net/weixin_49015143/article/details/135266293