Go 的 bufio 在内部忽略了有问题的 ErrBufferFull?

问题描述 投票:0回答:1

我在查看Go源码时发现,在

bufio.Reader.collectFragments
ReadSlice
ReadString
使用的助手)中,一个看似严肃的
ErrBufferFull
被忽略了,具体来说:

func (b *Reader) collectFragments(delim byte) (fullBuffers [][]byte, finalFragment []byte, totalLen int, err error) {
    var frag []byte
    // Use ReadSlice to look for delim, accumulating full buffers.
    for {
        var e error
        frag, e = b.ReadSlice(delim)
        if e == nil { // got final fragment
            break
        }
        if e != ErrBufferFull { // unexpected error
        ^^^^^^^^^^^^^^^^^^^^^ This ensures that ErrBufferFull will not break the loop
            err = e
            break
        }

        // Make a copy of the buffer.
        buf := bytes.Clone(frag)
        fullBuffers = append(fullBuffers, buf)
        totalLen += len(buf)
    }

    totalLen += len(frag)
    return fullBuffers, frag, totalLen, err
}

go/src/bufio/bufio.go,第446行,Go 1.22)

如果

ReadSlice
返回
ErrBufferNull
,则会被忽略。复制完整的缓冲区,并开始新的迭代,再次调用
ReadSlice

但是,当缓冲区已满时,

ReadSlice
“失败”,并且似乎没有任何逻辑来增长或清除已满的缓冲区。

func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
    s := 0 // search start index
    for {
        // Search buffer.
        if i := bytes.IndexByte(b.buf[b.r+s:b.w], delim); i >= 0 {
            i += s
            line = b.buf[b.r : b.r+i+1]
            b.r += i + 1
            break
        }

        // Pending error?
        if b.err != nil {
            line = b.buf[b.r:b.w]
            b.r = b.w
            err = b.readErr()
            break
        }

        // Buffer full?
        if b.Buffered() >= len(b.buf) {
            b.r = b.w
            line = b.buf
            err = ErrBufferFull
            break
        }

        s = b.w - b.r // do not rescan area we scanned before

        b.fill() // buffer is not full
    }

    // Handle last byte, if any.
    if i := len(line) - 1; i >= 0 {
        b.lastByte = int(line[i])
        b.lastRuneSize = -1
    }

    return
}

go/src/bufio/bufio.go,第347行,Go 1.22)

据我了解,这可能会导致

collectFragments
中的循环永远运行。然而,由于
ErrBufferFull
明确 忽略,我觉得这是设计使然,我错过了一些东西。

有人可以帮我理解吗?谢谢!

go io buffer
1个回答
0
投票

这在

ReadSlice
文档中进行了解释:

如果缓冲区在没有分隔符的情况下已满,ReadSlice 会失败并出现错误 ErrBufferFull。

您还应该注意到,如果返回 ErrBufferFull,则算法在将切片附加到另一个切片后继续读取,因此它会以块的形式读取。

© www.soinside.com 2019 - 2024. All rights reserved.