New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: io/fs: add writable interfaces #45757
Comments
I'm currently experimenting with writing a file format encoding/decoding/mutating package that is intended to work with files that aren't guaranteed to easily fit in memory. I would like to implement it in terms of This codec package doesn't want to care about supporting all the different places that the underlying files could be stored. It just wants to take in an Additionally, to make this package more testable, using Unfortunately, since |
I've got a similar issue with my p9 package. It attempts to implement a 9P client and server in a high-level way, similar to Maybe something like this could work? type RWFS interface {
FS
WriteFS
}
type WriteFS interface {
// Create creates a new file with the given name.
Create(string) (WFile, error)
// Modify modifies an existing file with the given name.
Modify(string) (WFile, error)
}
type WFile interface {
Write([]byte) (int, error)
Close() error
// Maybe also some kind of WStat() method?
} Then the returned types would only have to expose either reading or writing methods, and the interface would just handle it transparently. Persionally, I think that it would be a lot better if there was some way to abstract away the specific requirement of an |
To me, this looks like the minimum requirement: package fs
type WFile interface {
Stat() (FileInfo, error)
Write(p []byte) (n int, err error)
Close() error
}
type WriteFS interface {
OpenFile(name string, flag int, perm FileMode) (WFile, error)
} And another (ugh) for making dirs: type MkDirFS interface {
MkDir(name string, perm FileMode) error
} And some helper functions for convenience: func Create(fsys WriteFS, name string) (WFile, error) {
// Use fsys.OpenFile ...
}
func WriteFile(fsys WriteFS, name string, data []byte, perm FileMode) error {
// Use fsys.OpenFile, Write, and Close ...
}
func MkDirAll(fsys MkDirFS, path string, perm FileMode) error {
// Use fsys.MkDir to do the work.
// Also requires either Stat or Open to check for parents.
// I'm not sure how to structure that either/or requirement.
} |
I think that we should lean more heavily on io and os, rather than making top-level Summary
DetailSee sketch of an implementation here: https://gist.github.com/kylelemons/21539a152e9af1dd79c3775ca94efb60#file-io_fs_write_sketch-go This style of implementation appeals to me because:
I think the same patterns can be used to implement |
I think that also having a Just a small contribution as it feels to me in the scope of this proposal, and since no one mentionned file removal |
@kylelemons just to be consistent with fs.ReadDirFile, the only File extension at the moment, and iofs draft/The File interface: type ReadDirFile interface {
File
ReadDir(n int) ([]DirEntry, error)
}
type WriteFile interface {
File
Write(p []byte) (n int, err error)
} There is a comment from Russ Cox about this exact change as well. |
There's an interesting package https://pkg.go.dev/github.com/hack-pad/hackpadfs that's got some interfaces defined for a writable version of |
Go 1.16 introduced the
embed
andio/fs
packages. The current implementation is a minimal readable filesystem interface.This is a wonderful first step towards standardizing filesystem operations and providing the community with a lot of flexibility in how we implement filesystems. I would like us to take the next step and define a writable file system interface.
(FYI: I was surprised to not find an open issue for this, but maybe I missed something. Feel free to close if that's the case!)
Problem
fs.FS
can't be modified after it's defined.Optional interfaces could be defined in user-land:
But it suffers from the same issues that the readable filesystem interface aimed to solve: standardizing the interface across the ecosystem.
Use Cases
I'll list of few use-cases that I've come across since Go 1.16, but I'm sure the community has many more:
We've already seen started to see this pop up in the community around
io/fs
to address the problem in user-land:fs.MkdirAll
andfs.WriteFile
file.Write
,file.Seek
andfile.Close
.A quick search on Github will yield more community libraries: https://github.com/search?q=%22io%2Ffs%22+language%3Ago. For many of these implementations, you can imagine a useful writable implementation.
Of course, there are many other file system libraries that came before
io/fs
that define writable interfaces like afero and billy.Proposal
I don't feel qualified to define an interface, I know people have thought about this much harder than I have. What I would love to see from a community member's perspective is the following:
Nice to Have: Be able to define if a filesystem is readable, writeable or read-writable.
Thanks for your consideration!
The text was updated successfully, but these errors were encountered: