Hacker News new | ask | show | jobs
by nhanb 1317 days ago
Go's io/fs[0] design is one of the more successful ideas inspired by Plan 9 imho. If we can't have a 9p-centric OS, the next best thing is a 9p-like interface in a language's standard library.

For example, I have been developing a static site generator where I implement the output folder as an fs.FS[1]. The output generating code is now a simple function that copies from folder A to folder B, without even knowing that A is a virtual filesystem. Now how do I implement a preview server? Simply pass said filesystem to the standard library's http.FileServer. Done. (okay you actually have to pass it through the http.FS() adapter, but that's only because http.FileServer predates io/fs)

Of course this kind of abstraction can be done in any language, but Go explicitly specifies this interface, which can already be used by multiple utilities in the standard library (e.g. http.FileServer, go:embed). This nudges people to the same interoperable interface, and I'm all for it.

[0]: https://www.youtube.com/watch?v=yx7lmuwUNv8 [1]: https://pkg.go.dev/io/fs#FS

2 comments

While a great idea, Java and .NET did it first, on their standard libraries.
The Java version is much harder to implement than the go version.

FileSystem.Java: 12 abstract methods

FileStore.Java: 10 abstract methods

FileSystemProvider.java: 17 abstract methods

Total: 39 abstract methods

And having read through it, I’m still not sure what the role of these three systems are precisely. And there are more involved classes I ignored

Vs

fs.FS: 1 method

fs.File: 3 methods

fs.FileInfo: 6 methods

Total: 10

That’s 4 times less work for the developer. And 4 times less learning for users.

And it took me less time to look this up, and it’s abundantly clear that there is nothing I am missing here.

Generally in Go interfaces are much simpler than their Java equivalent.

In fact I’ll go further. The Java solution is so complicated that it is basically unused in practice.

It is more complicated, because it covers much more use cases, instead of just the basic.

Oh boy, it is used, starting by application servers.

so?
Like in most things, Go keeps catching up with modern language ecosystems.
I sense an air of derision, so I'll leave you with this: A lion ain't shit but a snack for three.
Do you have a link to your code? I thought fs.FS is read-only, so I’m curious where/how you bring writing data into it (“copies from folder A to folder B”)? Or do you mean that your implementation of fs.FS generates the content on-demand, when net/http serves it?
> Or do you mean that your implementation of fs.FS generates the content on-demand, when net/http serves it?

It's closer to this. The actual content was already written to an sqlite db, and my read-only FS allows reading that data back out but as a filesystem.

The admittedly not that interesting (and probably bad - I'm new to Go) code is here[1], and this "BlogFS" is used in 2 places:

- During "export" where it generates the static site. "Folder A" is my FS and "Folder B" is the destination i.e. an actual folder on the real filesystem.

- In a preview server that just serves "Folder A" directly.

[1]: https://git.sr.ht/~nhanb/bloghead/tree/40b70cadb01c14f1e3bf5...