Hello,

Up until now I've been in the habit of checking Close errors on files 
written to, but I never closed os.Stdout after use (for the purpose of 
error reporting), and now I'm thinking that's inconsistent.

In this commit message [1], Ian Lance Taylor wrote: "Programs should always 
check the error return of Close for a file opened for writing."

Does this imply that if I use os.Stdout I need to Close it and check the 
error? If no, why is that different?
I see no reason to expect weaker error reporting for stdout than any other 
file opened by the program itself.

For example gofmt doesn't close stdout, therefore this command could 
silently produce an incomplete output on a close-only error:
$ gofmt foo.go >bar.go

On the contrary, the Gnu coreutils for example, always close stdout and 
check the error, therefore this cat would report it and exit non-zero:
$ gofmt foo.go | cat >bar.go

It seems inconvenient to always Close and check os.Stdout after use: I 
would have to arrange for it in the majority of my programs, even the most 
simple.
But if I don't do that, why should I bother to check any os.File.Close 
error at all? In a class of equally important errors, if I'm ignoring some 
of them for no particular reason, I might as well ignore all of them.
What's your opinion?

In this old thread [2], Rob Pike wrote: "If the situation requires you to 
handle errors on close, handle them. If it does not, you can defer the 
close. That's all there is to it."

Specific situations may call for specific error handling, but unfortunately 
in the vast majority of cases there is little assumptions I can make. If 
the data is not on its way to the disc I want to tell the user, but not at 
the cost of much boilerplate if the condition is rare enough. I want to 
meet general expectations and be consistent.
(Telling the user usually means to print a message and/or make sure the 
exit status is non-zero.)

"defer f.Close()" is common in the wild, even for files written to. Many 
new users learn it as a general pattern because the read-only "requirement" 
is rarely discussed (for example Effective Go doesn't mention it in its 
"defer f.Close()" example).

It seems that, with most filesystem drivers, an EIO error that is not 
reported by Write has a high chance to be missed by Close too (unless you 
also call Sync), because a Close doesn't necessarily initiate any writeback 
from the kernel.
So I wouldn't worry about EIO from Close (unless I also use Sync) because I 
already accepted the compromise, therefore I'm left with ENOSPC or EDQUOT 
(i.e. "no space left" errors).
Is it possible that Write doesn't report ENOSPC or EDQUOT but Close does? 
According to the Linux close(2) man page, yes, on NFS; what about anything 
else?

The same man page was changed from: "Not checking the return value of 
close() is a common but nevertheless serious programming error"
to: "A careful programmer will check the return value of close()".
Now, that is helpful! :D

In summary I'm looking for a rule of thumb: should I check the Close error 
for files written to? Should I Close and check os.Stdout after use (for the 
purpose of error reporting)? For consistency I would expect either yes to 
both questions or no to both questions.
Thanks to anyone who read this far.

[1] 
https://github.com/golang/go/commit/6cbd737c8e4a5aa5a8e85895c5ee6ff53a358622
[2] https://groups.google.com/d/topic/golang-nuts/Hj7-HV-W_iU/discussion

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/21eff98e-a2b1-4cf1-8a90-e3d489e47b76%40googlegroups.com.

Reply via email to