转换自 'bufio.Reader“改为”io.ReadWriteCloser'

convert from `bufio.Reader` to `io.ReadWriteCloser`

提问人:user892960 提问时间:2/16/2023 更新时间:2/16/2023 访问量:232

问:

我有一个我想在不推进读者的情况下窥视它,io.ReadWriteCloser

所以我正在使用

bi := bufio.NewReader(i)
bi.Peek(1)

到目前为止一切顺利,但是后来当我想重用原始()时,它只有.io.ReadWriteCloseriEOF

所以我的问题是如何从 back 转换回bufio.Readerio.ReadWriteCloser

IO

评论

0赞 Sam Herrmann 2/16/2023
这回答了你的问题吗?如何重用原始字符串。Go 中的读者?
0赞 Sam Herrmann 2/16/2023
之后调用。i.Seek(0, 0)bi.Peek(1)
0赞 Cerise Limón 2/16/2023
@SamHerrmann 问题中提到的类型没有 Seek 方法。
1赞 Sam Herrmann 2/16/2023
右。也许这是一个 XY 问题,但如果没有更广泛的背景,就很难提供帮助。如果您需要查看函数内部,那么也许函数参数类型应该代替?据推测,您的原始阅读器的具体类型确实有一个方法,但它对您不可用,因为它作为 ?io.ReadWriteCloserio.ReadWriteSeekerio.ReadWriteCloserSeekio.ReadWriteCloser
0赞 user892960 2/16/2023
我为什么需要进入的原始问题在这里被问到 stackoverflow.com/questions/75465710/......希望这为这个问题增加了更多的背景。所以这只是实现所需行为的一种方式,两者兼而有之并不是初衷。Peek()io.ReadWriteCloserPeek()Seek()/Peak()

答:

0赞 Sam Herrmann 2/16/2023 #1

正如我在上面的评论中提到的,您需要访问原始读者的方法。这意味着将读者作为 an 传递是不够的。话虽如此,以下帮助程序函数可能是一种解决方法:Seekio.ReadWriteCloser

func peek(r io.Reader, n int) ([]byte, error) {
    bi := bufio.NewReader(r)
    peeked, err := bi.Peek(n)
    if err != nil {
        return nil, err
    }
    // Use type assertion to check if r implements the 
    // io.Seeker interface. If it does, then use it to
    // reset the offset.
    if seeker, ok := r.(io.Seeker); ok {
        seeker.Seek(0, 0)
    }
    return peeked, nil
}

现在你可以把 传递给这个函数。该函数检查读取器是否碰巧实现了该方法。如果该方法已实现,则将调用它。io.ReadWriteCloserpeekpeekSeekSeekpeek

评论

0赞 user892960 2/17/2023
另一个被接受的答案解决了我的问题,而无需调用io.Seeker.Seek()
3赞 Penny Stevens 2/16/2023 #2

因为 bufio.读取器缓冲来自底层读取器的数据,应用程序必须从 bufio 读取数据。调用 Peek 后的读者。

要获取 io。执行此操作的 ReadWriteCloser 包装 bufio。Reader 和原始 io。ReadWriteCloser:

// BufferedReadWriteCloser has all of the methods
// from *bufio.Reader and io.ReadWriteCloser.
type BufferedReadWriteCloser struct {
    *bufio.Reader
    io.ReadWriteCloser
}

func (rw *BufferedReadWriteCloser) Read(p []byte) (int, error) {
    return rw.Reader.Read(p)
}

以下是如何使用它:

rw := &BufferedReadWriteCloser{bufio.NewReader(i), i}
p, err := rw.Peek(1)

的值满足 io。ReadWriteCloser 接口。rw

没有要求或假设 io.ReadWriteCloser 具有 Seek 方法。

评论

0赞 user892960 2/16/2023
简洁的解决方案!创建两种类型的混合体,以便接口满足,而最重要的接口现在被“重定向”到io.ReadWriteCloserRead()bufio.Reader.Read()