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 WriteByte
the 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:
WriteByte
The method isWriter
a method of the structure, and the receiver isWriter
a pointer to the structureb
.- 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,
c
the single byte represented by the parameter is written to the buffer and the write pointer is updatedb.n
.
effect:
WriteByte
The 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 WriteRune
methods 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:
WriteRune
The method isWriter
a method of the structure, and the receiver isWriter
a pointer to the structureb
.r
First, it checks whether the Unicode code point can be represented by a byte, and if so, callsWriteByte
the 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
, callWriteString
the method to write the Unicode code point as a string. - Finally, use
utf8.EncodeRune
Encode the Unicode code point into a sequence of bytes, updating the write pointer.
effect:
WriteRune
Method 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.EncodeRune
encoding using . - Returns the number of bytes written and any errors.
29. WriteString: Write a string
This part of the code defines WriteString
methods 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:
WriteString
The method isWriter
a method of the structure, and the receiver isWriter
a pointer to the structureb
.- Inside the method, the string is processed in a loop
s
until 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.wr
isStringWriter
an implementation of the interface, an attempt is made to delegate the write operation directly to the underlying writerStringWriter
. - 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
nn
and update the strings
. - 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:
WriteString
The 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
StringWriter
interface 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 ReadFrom
methods for implementing io.ReaderFrom
the interface. If the underlying writer supports ReadFrom
the method, this method will call the underlying ReadFrom
method. If buffered data and underlying support are present ReadFrom
, ReadFrom
the 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:
ReadFrom
The method isWriter
a method of the structure, and the receiver isWriter
a pointer to the structureb
.- 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.wr
implementsio.ReaderFrom
the interface and whether there is underlying supportReadFrom
. - 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
ReadFrom
and the buffer is empty, call the underlyingReadFrom
method directly to write the readerr
's data to the underlying writer and return the number of bytes read and an error. - If the underlying layer does not support it
ReadFrom
or the buffer is not empty, the data is read from the readerr
to 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 timeb.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:
ReadFrom
Method used to read data from a readerr
and write it to the underlying writer.- If the underlying layer supports it , efficient data transmission is achieved
ReadFrom
by 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 ReadWriter
a structure, which contains pointers to Reader
and Writer
, and implements io.ReadWriter
the 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:
ReadWriter
Is a structure containing two pointer members:Reader
andWriter
. These two pointers point toReader
structure andWriter
structure respectively.- The structure implements
io.ReadWriter
the interface, which means it can be read and written simultaneously. NewReadWriter
The function is used to allocate and return a new oneReadWriter
. The function receives aReader
and aWriter
and assigns them respectively toReadWriter
the members of the structure.
effect:
ReadWriter
Structures are designed to provide buffered input and output capabilities, allowing reading and writing operations to them.- By combining
Reader
andWriter
together, the ability to read and write simultaneously is achieved. NewReadWriter
The function creates a newReadWriter
instance and associates the givenReader
andWriter
to the instance.