如何获得一个实现 io.WriteCloser 的 bufio.Writer

Rob*_*ert 6 io go

我想扩展以无缓冲方式将数据写入文件的现有代码。

代码需要一个实现io.WriteCloser接口的编写器。因此,仅用 a 包装现有文件是bufio.Writer行不通的,因为它没有实现此接口。

我怎样才能bufio.Writer实现并将必要的关闭调用传递给底层文件?

icz*_*cza 6

io.WriteCloser 是界面:

type WriteCloser interface {
        Writer
        Closer
}
Run Code Online (Sandbox Code Playgroud)

最终“规定”了这两种方法:

Write(p []byte) (n int, err error)

Close() error
Run Code Online (Sandbox Code Playgroud)

bufio.Writer已经有一个Write()方法,所以要使它成为一个WriteCloser,只Close()需要一个方法。

bufio.Writer使用 noopClose()方法扩展:

type MyWriteCloser struct {
    *bufio.Writer
}

func (mwc *MyWriteCloser) Close() error {
    // Noop
    return nil
}
Run Code Online (Sandbox Code Playgroud)

type 的*MyWriteCloser值现在是 a WriteCloser。这是最简单的扩展。使用它:

bw := bufio.NewWriter(w)

mwc := &MyWriteCloser{bw}
Run Code Online (Sandbox Code Playgroud)

尽管我们可以——而且应该——添加一个更有意义的Close()方法。与bufio.Write缓冲写入一样,我们应该在声明它关闭之前刷新它的内部缓冲区:

func (mwc *MyWriteCloser) Close() error {
    return mwc.Flush()
}
Run Code Online (Sandbox Code Playgroud)

还要注意,由于bufio.Write无法关闭(不提供Close()方法),因此不会关闭其底层io.Writer,这只是为了符合io.Closerio.WriteCloser接口。

如果您还想关闭底层文件,您还必须存储它,并且在调用后bufio.Flush()(以确保所有内容都已写出),鉴于它没有返回任何错误,您也可以继续关闭该文件。

这是它的样子:

type MyWriteCloser struct {
    f *os.File
    *bufio.Writer
}

func (mwc *MyWriteCloser) Close() error {
    if err := mwc.Flush(); err != nil {
        return err
    }
    return mwc.f.Close()
}
Run Code Online (Sandbox Code Playgroud)

使用它:

// Open a file:
f, err := os.Open("myfile.txt")
if err != nil {
    panic(err) // Handle error
}

mwc := &MyWriteCloser{f, bufio.NewWriter(f)}
defer mwc.Close()

// use mwc
Run Code Online (Sandbox Code Playgroud)