Hacker News new | past | comments | ask | show | jobs | submit login

The manual memory management thing -- like needing GC -- feels like a false dichotomy. Most of these languages that have GC need you to "manually" manage resource lifetimes anyways for a lot of resources: files, network connections. If you're making a UI, you think about when components are mounted and unmounted. The logic for all this is domain logic and part of the code for your program. Memory is just one such resource, and I think there should be more acknowledgement of it as such by languages, instead of just piling it up and kicking a "GC cycle" to clean it up whenever, leading to pauses in interactive programs and whatnot (Go's GC, and Go in general, do not perform well under WASM in my experience).

In Go you have to "manually" defer a file.Close() call -- vs. the destructor getting automatically called in C++ (it even gets automatically called when a containing object is destructed, if it's a member, and so on). Go's version doesn't seem very "automatic" to me.

The simplicity of Go actually hides a lot of runtime complexity that is happening: the GC, map lookups, scheduling of goroutines and so on. Which you have to understand and then ultimately learn how to tune from a distance (because you don't have direct control) for a lot of applications where it matters. For server applications (where the hardware is under your control) and also CLI tools (which can just run, only allocate memory, then just exit), this matters less. If your code is running on user's devices as an interactive application, it feels to me like how it performs on and uses their actual hardware is part of your responsibility as the developer, and some things about Go make that harder to do. Like you have to think about the GC and try to avoid it ("from a distance") if you run into that (which you do quickly in WASM, and which eg. Gio tries to explicitly design around, and so on).

I want to see languages that care about simplicity and also include such deterministic resource management as part of their design and offering.




> In Go you have to "manually" defer a file.Close() call -- vs. the destructor getting automatically called in C++ (it even gets automatically called when a containing object is destructed, if it's a member, and so on). Go's version doesn't seem very "automatic" to me.

To clarify this one point, Go allows you to attach a destructor (finalizer) to an object, but since the language is garbage collected, there’s no guarantee of when the destructor will be called, if ever, since disabling the garbage collector is entirely possible, even if not advisable.

The File object will Close the file when the Finalizer runs, since the standard library attaches a finalizer to it, but you should defer the Close to deterministically ensure that the file is closed when you expect it to be closed, and to free that OS resource of a file handle as soon as possible, since some OSes limit how many you can have at a given time. Finalizers also won’t be run when the program exits, which is fine for most things, but you’ll want to have ensured any buffers were flushed before then, and defer can guarantee that.

Languages like Rust and C++ have deterministic destruction at the end of a given scope thanks to RAII, so it makes sense for them to lean more heavily on destructors there.

Java File*Stream objects should have “close()” called on them, from what I’m seeing on a Google search, so this doesn’t seem to be a surprising pattern for a garbage collected language. I know in Python you’re encouraged to use a “with” block to ensure that file objects get closed.

https://golang.org/pkg/runtime/#SetFinalizer




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: