4 ms·
How do you feel about v, err := foo.Open() // … defer func() { if closeErr := v.Close(); closeErr != nil { err = fmt.Errorf("wh
by catlifeonmars 1y ago
How do you feel about
v, err := foo.Open()
// …
defer func() {
if closeErr := v.Close(); closeErr != nil {
err = fmt.Errorf("while closing %w: %v", err, closeErr)
}
}()
// …
When you’re writing something trivial/pure, Go’s error handling is fine, if maybe a tad bit verbose, but it quickly becomes nightmarish when you start to do nontrivial things that are typical for systems programming.
FWIW I love Go, it’s my daily driver for most things. I still think it can get messy far too quickly
- database64128 1y agoJust write `defer v.Close()`? In almost all cases, `close(2)` errors can be safely ignored. Rust also does this: https://github.com/rust-lang/rust/blob/792fc2b033aea7ea7b766e38bdc40f7d6bdce8c3/library/std/src/os/fd/owned.rs#L169-L196 https://github.com/rust-lang/rust/blob/792fc2b033aea7ea7b766...
- catlifeonmars 1y agoI don’t think you want to do this for files you’ve opened for writing. In fact it’s quite common to “commit” on close, at least from what I’ve seen.
- database64128 1y ago> In fact it’s quite common to “commit” on close, at least from what I’ve seen. close(2) does not "commit". You have to call v.Sync() (i.e. fsync(2)) for that. From man 2 close: A successful close does not guarantee that the data has been successfully saved to disk, as the kernel uses the buffer cache to defer writes. Typi‐ cally, filesystems do not flush buffers when a file is closed. If you need to be sure that the data is physically stored on the underlying disk, use fsync(2). (It will depend on the disk hardware at this point.)
- catlifeonmars 1y agoI think we’re talking past each other. I was not talking about file descriptors; rather I was talking about the fact that it’s common for Go libraries to do interesting and useful things when you call the `Close()` method on a type. `Close()` is idiomatic go for resource cleanup. You might wait until close to populate a length and or checksum field in a message header. Or close could submit a buffer of log events to a remote aggregation endpoint. I’m not saying I agree with APIs that are designed that way, but it’s common enough that you should assume the error return value is significant unless you know otherwise (for Go)