-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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: os/v2: File should be an interface #14106
Comments
Related: #5636 (VFS layer), in which we were never able to find a design that fit everybody's needs. |
https://godoc.org/golang.org/x/net/webdav#FileSystem This may be one of implementations. |
I think I'd argue that io.File should be the interface but it's all moot now. |
rsc How about follow interface? type FileV2 interface{
io.ReadWriteCloser
//....
}
func NewFileFromV2(v2 FileV2) *File{
//...
} |
No. Please see my reply to a similar suggestion in #13473. Having version
numbers in APIs is really ugly.
|
This is a long-term issue that we are not actively working on. |
After several years of maintaining various Google filesystem implementations, I disagree strenuously with this proposal. Go interfaces act as bounds on types. On function inputs, they are lower bounds: every implementation must provide at least the methods described in the interface. On function outputs, they are upper bounds: even if the implementation provides methods beyond those in the interface, they are not visible in the compile-time type system, and they are therefore also less visible in the documentation. Because they act as bounds, interfaces work best on the consumer side of an API: for example, Turning that observation back toward the If we were to make In exchange for that cost, we would get very little benefit. It is already possible today for any package to define and use an interface with an arbitrary subset of the methods provided by |
Would you agree with adding symbols to ioutil so that we can pass it filesystem implementations? Whoever writes a file system implementation is now forced to duplicate ioutil functions. |
An alternative would be to split the implementation. Leave type File interface {
Reader
Writer
Seeker
ReaderAt
WriterAt
Syncer // Doesn't exist, but you never know. Maybe `Flusher` instead?
Close
} This is analogous to the difference between In this case, an extra
This is very true, but I think there's some merit to having a standard of some kind. The Although, there is technically |
Yes to adding symbols, no to |
And we don't want to go overkill on optional interfaces because experience with Also, changing CounterproposalIf one of the primary motivations for this is to implement VFS packages that return files, the real problem is there's no way to instantiate arbitrary We could instead add constructor func(s) to return // NewReaderAtFile returns an *os.File given the provided stat information and ReaderAt.
// The file is assumed to be a regular file with size fi.Size(), backed by the data in contents.
func NewReaderAtFile(fi FileInfo, contents io.ReaderAt) *os.File You could imagine a few of those for various types (regular files, symlinks, directories). For misc methods like |
I addition, this counterproposal would have a nice solution to #13473 too. Instead of that bug's: os.Stdout = bufio.NewWriter(os.Stdout)
os.Stderr = bufio.NewWriter(os.Stderr) You'd instead write something like: os.Stdout = os.NewWritableFile(bufio.NewWriter(os.Stdout))
os.Stderr = os.NewWritableFile(bufio.NewWriter(os.Stderr)) So the type of |
@bradfitz, what would the |
Either return |
I note that we went this route a bit with the *net.Resolver type. It's a concrete type instead of an interface so it can have a dozen methods, but if you want to customize its behavior you can shove a DNS-acting Dial func into it and do whatever behavior you want. (see #12503 and dup #17554) |
I agree that that approach works around many of the maintainability problems of interfaces, but I still don't understand why it belongs in the |
Can we maybe start with making a overview of what is currently a interface and what is not? Example https://golang.org/src/os/types.go?s=369:411#L6 Sure there is a perfect reason for why one is a struct and the other a interface. We only have one shot to make it so that everything get to be in harmony again that developers can predict with almost 100% accuracy if something going to be a struct or a interface without looking at the code. I suggest we must first create a world map where we define interface or struct countries, but for me your proposal is already like a street name in a unknown country where you need to explain to the mail man to use the godoc stars to navigate his airplane I think we are skipping a step here and need to zoom way out just to make sure we have this logic harmony now that we have the chance to finally fix the world map after 10 years. So basically what I am trying to convince is that if A and B is a interface C must be too. Not saying your solution is bad I simply want a complete interface list that make sense first. Thanks |
I just want to to be able to make them not be files at all. VFS is a different - important, but different - case. |
By analogy with #13473, os.File should also be an interface. That would permit a program to use files in the abstract sense, including implementations not provided by the os package.
The text was updated successfully, but these errors were encountered: