I’ve run quite a few times into this issue lately. I have an io.Reader which
wraps another io.Reader but does not offer a way to close the inner
io.Reader.
One instance of this issue is with the bufio.Reader type. The function below
opens the given file, peeks at the first 512 bytes to try to detect the
mime type, and then returns an io.ReadCloser to read and then close the file.
| |
This code does not compile because bufio.Reader does not implement the
io.Closer interface. Returning just an io.Reader would not be ideal because
the opened file would get leaked, at least until the garbage collector runs.
There is an elegant pattern to fix this issue. The FuncCloser pattern, as
opposed to io.NopCloser allows one to add an arbitrary Close() error
function to an io.Reader, turning it into an io.ReadCloser.
The code above could be fixed easily by modifying the return line to:
| |
More complex closing behavior can also be achieved by using a closure. Imagine
that file is actually a temporary file that we must remove once we’re done
using it. We can easily close and remove it like so:
| |
Implementing this pattern in your project is trivial:
| |
The pattern might be useful for io.Writer/io.WriteCloser as well!