Go语言 从“缓冲读取器”转换为“IO读写关闭器”

0yycz8jy  于 2023-02-27  发布在  Go
关注(0)|答案(2)|浏览(210)

我有一个io.ReadWriteCloser,我想在不推进阅读器的情况下查看它,
所以我用

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

到目前为止一切顺利,但后来当我想重用原来的io.ReadWriteCloseri)它只有EOF
我的问题是如何将bufio.Reader转换回io.ReadWriteCloser

8aqjt8rx

8aqjt8rx1#

因为bufio.Reader缓冲来自基础读取器的数据,所以应用程序必须在调用Peek之后从bufio.Reader读取数据。
要获得一个这样做的io. ReadWriteCloser,请 Package 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)

rw的值满足io.ReadWriteCloser接口。
不要求或假设io.ReadWriteCloser具有Seek方法。

xuo3flqw

xuo3flqw2#

正如我在上面的评论中提到的,您需要访问原始读取器的Seek方法,这意味着将读取器作为io.ReadWriteCloser传递是不够的,下面的helper函数可能是一种解决方法:

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.ReadWriteCloser传递给peek函数,peek函数检查读取器是否实现了Seek方法,如果实现了Seek方法,那么peek将调用它。

相关问题