如何获取一个实现了io.WriteCloser接口的bufio.Writer对象?

huangapple go评论94阅读模式
英文:

How to get a bufio.Writer that implements io.WriteCloser

问题

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

该代码期望一个实现了io.WriteCloser接口的写入器。因此,仅仅用bufio.Writer包装现有文件是行不通的,因为它没有实现这个接口。

我该如何使bufio.Writer实现并传递必要的关闭调用给底层文件?

英文:

I want to extend existing code that writes data to a file in an unbuffered way.

The code expects a writer that implements the io.WriteCloser interface. Therefore just wrapping the existing file with a bufio.Writer does not work, as it does not implement this interface.

How can I make a bufio.Writer to implement and pass the necessary close call to the underlaying file?

答案1

得分: 9

io.WriteCloser 是一个接口:

type WriteCloser interface {
        Writer
        Closer
}

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

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

Close() error

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

通过给 bufio.Writer 添加一个空的 Close() 方法来扩展它:

type MyWriteCloser struct {
	*bufio.Writer
}

func (mwc *MyWriteCloser) Close() error {
	// 空操作
	return nil
}

现在,类型为 *MyWriteCloser 的值就是一个 WriteCloser。这是最简单的扩展方式。使用它:

bw := bufio.NewWriter(w)

mwc := &MyWriteCloser{bw}

虽然我们可以 - 也应该 - 添加一个更有意义的 Close() 方法。由于 bufio.Writer 执行缓冲写入,所以在声明它关闭之前,我们应该先刷新其内部缓冲区:

func (mwc *MyWriteCloser) Close() error {
	return mwc.Flush()
}

还要注意的是,由于 bufio.Writer 不能被关闭(没有提供 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()
}

使用方法:

// 打开一个文件:
f, err := os.Open("myfile.txt")
if err != nil {
    panic(err) // 处理错误
}

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

// 使用 mwc
英文:

io.WriteCloser is the interface:

type WriteCloser interface {
        Writer
        Closer
}

Which ultimately "prescribes" these 2 methods:

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

Close() error

bufio.Writer already has a Write() method, so to make it a WriteCloser, only a Close() method is needed.

Extending bufio.Writer with a noop Close() method:

type MyWriteCloser struct {
	*bufio.Writer
}

func (mwc *MyWriteCloser) Close() error {
	// Noop
	return nil
}

A value of type *MyWriteCloser is now a WriteCloser. This is the easiest extension. Using it:

bw := bufio.NewWriter(w)

mwc := &MyWriteCloser{bw}

Although we can –and we should– add a more meaningful Close() method. As bufio.Write does buffered writes, we should flush its internal buffer before we declare it closed:

func (mwc *MyWriteCloser) Close() error {
	return mwc.Flush()
}

Also note that since bufio.Write cannot be closed (does not provide a Close() method), this will not close its underlying io.Writer, this is just to conform to the io.Closer and io.WriteCloser interfaces.

If you also want to close the underlying file, you also have to store it, and after calling bufio.Flush() (to make sure everything is written out), given it's not returning any errors, you may proceed to also close the file.

This is how it could look like:

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()
}

Using it:

// 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

huangapple
  • 本文由 发表于 2017年3月30日 18:49:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/43115699.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定