Go源码学习:bufio包 - 1.1 - bufio.go -(4)

bufio包官方文档

Go源码学习-索引目录

bufio包学习的上一篇文章:Go源码学习:bufio包 - 1.1 - bufio.go -(3)

27、WriteByte:写入单个字节

这部分代码定义了 WriteByte 方法,用于将单个字节写入缓冲区。

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

解释:

  • WriteByte 方法是 Writer 结构体的方法,接收者为指向 Writer 结构体的指针 b
  • 首先,检查是否存在错误,如果存在直接返回错误。
  • 然后,检查缓冲区的可用空间是否足够,以及执行刷新操作是否成功,如果不成功则返回错误。
  • 最后,将参数 c 表示的单个字节写入缓冲区,并更新写指针 b.n

作用:

  • WriteByte 方法用于将单个字节写入缓冲区,常用于按字节写入数据。
  • 在写入之前,会进行错误检查,包括缓冲区空间是否足够以及刷新操作的成功与否。
  • 写入操作成功后,更新写指针,准备写入下一个字节。

28、WriteRune:写入单个Unicode码点

这部分代码定义了 WriteRune 方法,用于写入单个Unicode码点,返回写入的字节数和任何错误。

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

解释:

  • WriteRune 方法是 Writer 结构体的方法,接收者为指向 Writer 结构体的指针 b
  • 首先,检查 Unicode 码点 r 是否可以用一个字节表示,如果是,调用 WriteByte 方法直接写入。
  • 然后,检查是否存在错误,如果存在直接返回错误。
  • 获取缓冲区的可用空间 n
  • 如果可用空间小于 utf8.UTFMax,执行刷新操作。
  • 再次获取可用空间,如果仍然小于 utf8.UTFMax,调用 WriteString 方法写入字符串形式的 Unicode 码点。
  • 最后,使用 utf8.EncodeRune 将 Unicode 码点编码为字节序列,更新写指针。

作用:

  • WriteRune 方法用于将单个 Unicode 码点写入缓冲区,可以处理多字节的 Unicode 码点。
  • 在写入之前,会进行一系列的检查和操作,包括判断是否可以用一个字节表示,刷新缓冲区,以及使用 utf8.EncodeRune 进行编码。
  • 返回写入的字节数和任何错误。

29、WriteString:写入字符串

这部分代码定义了 WriteString 方法,用于写入字符串。它返回写入的字节数以及可能的错误信息。

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

解释:

  • WriteString 方法是 Writer 结构体的方法,接收者为指向 Writer 结构体的指针 b
  • 在方法内部,通过循环处理字符串 s,直到全部写入或者发生错误。
  • 在每次迭代中,检查剩余空间是否足够容纳当前字符串,并且没有发生错误。
  • 如果缓冲区为空且底层写入器 b.wrStringWriter 接口的实现,则尝试将写入操作直接委托给底层的 StringWriter
  • 如果缓冲区不为空,或者无法委托给 StringWriter,则采用常规的拷贝(copy)方式将字符串写入缓冲区,并在必要时进行刷新。
  • 累计写入的字节数 nn,并更新字符串 s
  • 最后,如果存在错误,返回累计的字节数和错误;否则,返回累计的字节数和 nil

作用:

  • WriteString 方法用于将字符串写入缓冲区,处理了缓冲区大小不足以容纳整个字符串的情况。
  • 在写入之前,会尝试将写入操作委托给底层的 StringWriter 接口,以提高效率。
  • 返回写入的字节数以及可能的错误信息。

30、ReadFrom:从读取器读取数据

这部分代码定义了 ReadFrom 方法,用于实现 io.ReaderFrom 接口。如果底层写入器支持 ReadFrom 方法,该方法将调用底层的 ReadFrom 方法。如果存在缓冲数据和底层支持 ReadFrom,则在调用 ReadFrom 之前填充缓冲区并写入数据。

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

解释:

  • ReadFrom 方法是 Writer 结构体的方法,接收者为指向 Writer 结构体的指针 b
  • 在方法内部,首先检查是否存在错误,如果有,直接返回零字节和错误。
  • 然后,检查底层写入器 b.wr 是否实现了 io.ReaderFrom 接口,以及是否存在底层支持 ReadFrom 的情况。
  • 在循环中,如果缓冲区可用空间为零,首先尝试刷新缓冲区,以确保有足够的空间用于写入数据。
  • 如果底层支持 ReadFrom 且缓冲区为空,直接调用底层的 ReadFrom 方法,将读取器 r 的数据写入底层写入器,并返回已读取的字节数和错误。
  • 如果底层不支持 ReadFrom 或者缓冲区非空,通过循环从读取器 r 中读取数据到缓冲区,直到达到最大的连续空读次数。
  • 将读取到的数据数量累加到总字节数 n 中,同时更新缓冲区的写指针 b.n
  • 如果发生错误,退出循环。
  • 最后,如果错误为 io.EOF,则在缓冲区刚好填满的情况下提前刷新,以确保所有数据写入。

作用:

  • ReadFrom 方法用于从一个读取器 r 中读取数据,并将其写入底层写入器。
  • 如果底层支持 ReadFrom,通过调用底层的 ReadFrom 方法实现高效的数据传输。
  • 同时,会考虑缓冲区的状态,确保有足够的空间用于写入数据。

31、ReadWriter:带缓冲的输入和输出

这部分代码定义了 ReadWriter 结构体,它包含指向 ReaderWriter 的指针,并实现了 io.ReadWriter 接口。

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

解释:

  • ReadWriter 是一个结构体,包含了两个指针成员:ReaderWriter。这两个指针分别指向 Reader 结构体和 Writer 结构体。
  • 结构体实现了 io.ReadWriter 接口,这意味着它可以同时进行读和写操作。
  • NewReadWriter 函数用于分配并返回一个新的 ReadWriter,该函数接收一个 Reader 和一个 Writer,并将它们分别赋值给 ReadWriter 结构体的成员。

作用:

  • ReadWriter 结构体的设计旨在提供带缓冲的输入和输出功能,允许对其进行读取和写入操作。
  • 通过将 ReaderWriter 结合在一起,实现了同时进行读和写的能力。
  • NewReadWriter 函数用于创建一个新的 ReadWriter 实例,并将给定的 ReaderWriter 关联到该实例中。

猜你喜欢

转载自blog.csdn.net/weixin_49015143/article/details/135266293
今日推荐