I find myself constantly needing to look up the documentation for io and io/ioutil to figure out which package contains the thing I want to use.
The root of the problem is that ioutil isn't a coherent abstraction boundary. The suffix util doesn't add any information — if a package has no utility, it should not exist! — and the remaining information in the package name doesn't distinguish it from io. (See also the "Bad package names" section of https://blog.golang.org/package-names.)
From what I can tell, the main purpose of separating out ioutil is to reduce the dependencies of io: specifically, the dependencies on bytes, os, and sort.
In a potential Go 2, I propose to resolve those dependencies by refactoring the ioutil package as follows:
Move Discard, NopCloser, and ReadAll into package io:
NopCloser has no dependencies.Discard depends on sync, which io already depends on.ReadAll uses a bytes.Buffer internally, but doesn't actually need very much of its API; it can be rewritten easily to avoid that dependency.Move ReadDir, ReadFile, TempDir, TempFile, and WriteFile to a new package, io/fileio.
File suffix: fileio.Read instead of ioutil.ReadFile.io.ReadFull / ioutil.ReadAll pair is especially frustrating.
To take the logic a bit further with respect to removing chattiness, how about (or: why not?) one step further: io/file instead of io/fileio. Then it's file.Read instead of fileio.Read. file and io together seem tautological. Especially when you throw in Read/Write, etc.
Sounding them out: file.Read, file.Write, file.Temp, file.ReadDir, file.TempDir, etc. Side thought: Maybe the latter two would read better as dir.Read and dir.Temp, if there was a io/dir package?
There may be good arguments for io/fileio instead of io/file? One that comes to mind is that people might want to call variables dir and file. Not sure if that's a much of a problem in practice or not.
One that comes to mind is that people might want to call variables dir and file. Not sure if that's a much of a problem in practice or not.
Looks like this will be a huge problem, same as net/url or path.
There may be good arguments for
io/fileioinstead ofio/file? One that comes to mind is that people might want to call variablesdirandfile. Not sure if that's a much of a problem in practice or not.
I agree with @cristaloleg: this is absolutely a problem in practice. file and dir are incredibly common, useful variable names. To quote the Package names blog post from 5 years ago:
Don't steal good names from the user. Avoid giving a package a name that is commonly used in client code. For example, the buffered I/O package is called
bufio, notbuf, sincebufis a good variable name for a buffer.
Should this proposal be closed because of #42026 ?
Yes, thanks.
Most helpful comment
To take the logic a bit further with respect to removing chattiness, how about (or: why not?) one step further:
io/fileinstead ofio/fileio. Then it'sfile.Readinstead offileio.Read.fileandiotogether seem tautological. Especially when you throw in Read/Write, etc.Sounding them out:
file.Read,file.Write,file.Temp,file.ReadDir,file.TempDir, etc. Side thought: Maybe the latter two would read better asdir.Readanddir.Temp, if there was aio/dirpackage?There may be good arguments for
io/fileioinstead ofio/file? One that comes to mind is that people might want to call variablesdirandfile. Not sure if that's a much of a problem in practice or not.