我想扩展以无缓冲方式将数据写入文件的现有代码。
代码需要一个实现io.WriteCloser接口的编写器。因此,仅用 a 包装现有文件是bufio.Writer行不通的,因为它没有实现此接口。
我怎样才能bufio.Writer实现并将必要的关闭调用传递给底层文件?
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.Closer和io.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)