7 ms·
> Go is a language that gets out of your way, encourages you to solve your problem Maybe I'm just too dumb for Go, but this is not consistent with my experienc
by mcronce 4y ago
> Go is a language that gets out of your way, encourages you to solve your problem
Maybe I'm just too dumb for Go, but this is not consistent with my experience at all. Go's insistence on pretending that complexity doesn't exist would get in my way all the time. Go's extreme hostility toward FFI calls got in my way several times.
- zozbot234 4y ago> Go's inane hostility toward FFI calls got in my way several times. All languages w/ obligate GC are "hostile" to FFI in some way or another. The Go default implementation also uses split stacks or something for its goroutines, that cannot feasibly interop with FFI code. But it's usually easy enough to just isolate Go code to it's own process/address space and use IPC or network communication to enable the interop one would usually achieve via FFI.
- mcronce 4y agoSerializing a request structure, making an IPC/network call, deserializing the request structure, serializing the response structure, sending it back, and deserializing it ... isn't really a solution when the purpose of an FFI call is typically to fix some performance issue. Lots of garbage-collected languages make FFI not only easy but plenty fast. Go does neither.
- throwaway894345 4y agoI started out thinking that fast and easy FFI was ideal and being disappointed that Go's FFI was neither. I've since changed my opinion as it's really nice that one can usually get away without pulling any C dependencies into their dependency tree. I wrote more in the sibling comment: https://news.ycombinator.com/item?id=31194347 https://news.ycombinator.com/item?id=31194347
- mcronce 4y agoThat would be great if Go provided better performance. With its awful FFI, you have no recourse when you hit its limits other than to rewrite the entire codebase in something else. As with many things, there's nothing stopping you from just sticking with pure Go if you don't like C toolchains. While C build issues are a valid theoretical concern, in practice I've never had any Python package fail to install because of a C dependency problem that wasn't trivially resolved, nor any Rust project fail to compile because of a C dependency problem at all.
- throwaway894345 4y ago> That would be great if Go provided better performance. With its awful FFI, you have no recourse when you hit its limits other than to rewrite the entire codebase in something else. I wouldn't know. I've never run into an issue where Go's performance was a real bottleneck, and anyway every mainstream language with easy FFI still has significant FFI overhead (so much so that many programs actually run slower with FFI). This isn't really true for Rust (Rust makes it easy to define types which are essentially C structs and thus require little/no marshaling), but performance also isn't the reason you FFI out of Rust. > As with many things, there's nothing stopping you from just sticking with pure Go if you don't like C toolchains. Right, that's my point. You viably can stick with pure Go because such a large share of the Go ecosystem is pure because FFI is rarely worth the hassle. > While C build issues are a valid theoretical concern, in practice I've never had any Python package fail to install because of a C dependency problem that wasn't trivially resolved Try building a significant Python project on anything except a recent version of RHEL, Debian, MacOS, or Windows. For example, try getting your Python project running on something like a scratch Docker container. Or try packaging a Python package (which depends even transitively on a C library, especially one which isn't already packaged for Nix) with Nix.
- mcronce 4y ago> every mainstream language with easy FFI still has significant FFI overhead (so much so that many programs actually run slower with FFI). This isn't really true for Rust This isn't true for almost any language to the extent it's true for Go, and for many compiled languages it isn't really true at all. > Try building a significant Python project on anything except a recent version of RHEL, Debian, MacOS, or Windows. For example, try getting your Python project running on something like a scratch Docker container. Or try packaging a Python package (which depends even transitively on a C library, especially one which isn't already packaged for Nix) with Nix. While these are legitimate theoretical problems, none of them are really problems in practice. Containers don't need to be scratch, and if you're building a Python project, you're already not running a scratch container, so the addition of FFI doesn't change that. Nix is not an environment I've ever seen a requirement to support, let alone had a requirement. It really seems to me that you like Go and you like Go's design decisions, but "I like this" is not the same as "this is better than that". I'm not particularly interested in rehashing the same conversation over and over again.
- throwaway894345 4y agoInversely, virtually all languages with "easy FFI" end up being even more hostile in that a significant chunk of the ecosystem depends on C build tooling which is almost always fragile: C build systems have implicit dependency management, so you don't know what dependencies you need to have installed on your system or where they need to be installed. This means that something which builds on one machine may fail to build on another machine (in the case of build-time dependencies) or that it may run on one machine but not another (in the case of run-time dependencies). It's also opaque to the host build system, so cross compilation becomes dramatically more difficult. Lastly, C is inherently unsafe and insecure in ways that most host languages are not. In practice, whether by accident or design, the Go ecosystem is really, really nice because it avoids FFI to a high degree. An overwhelming majority of programs can be cross compiled into a truly static binary (it may not even depend on libc unless--as is the case with Windows and MacOS--the host platform requires it). It also means that there are very few "C-shaped libraries", by which I mean thin bindings around some C library which exposes idiomatic C semantics rather than idiomatic Go semantics. Moreover, your programs aren't running a bunch of inherently unsafe code under the hood, and are consequently more likely to be secure as a result. It's kind of nice that C FFI is possible such that libraries which are unlikely to be ported to Go (e.g., ffmpeg) or which cannot be ported to Go (e.g., opengl) are still available, but not so easy that people pull in C libraries for every little convenience.
- nicoburns 4y agoThe Rust ecosystem does one better and packages the C libraries and build configuration (including making it portable across platforms) as part of the crate. So you just add the dependency to your Cargo.toml and the C library will build as part of the regular `cargo build` process.
- mcronce 4y agoAnd as a bonus, be statically linked with all the benefits that brings.
- throwaway894345 4y ago
- jen20 4y ago> The Go default implementation also uses split stacks or something for its goroutines This has not been true since Go 1.2, back in late 2013.
- zozbot234 4y agoThe fact remains that you need a separate implementation (cgo) if you want to do FFI. It might be something else goroutine-related that blocks FFI in the default Go implementation, but the issue is still there either way.
- preseinger 4y agoFFI isn't important. It's a niche feature for a superminority of use cases.
- throwaway894345 4y agoWhat do you mean "a separate implementation"? CGo is part of Go, it's not another implementation of Go.
- surrealize 4y agoSeparate in the "CGo is not Go" sense.
- giraffe_lady 4y ago> Go's insistence on pretending that complexity doesn't exist Probably the most accurate and concise summary of my problems with go also.
- tialaramex 4y agoI am usually unhappy/ worried working in a language or library that pretends the world is simpler than I know it really is. On a good day there is documentation clearly explaining that the maintainers know about the complexity and here's what they've done about that so at least I know; on a bad day it's just shrug emoji. The article mentions the whole filename thing as an example, and that's one of the first places where I felt I was at home with Rust. It's not unnecessarily complicated but it does force me to acknowledge that yeah, the name of a file might be incoherent nonsense. It's probably a String, but it might not be. I can write code that says "I don't care, we're probably fine" and accept that if it's not fine the code will fail at runtime in a defined way - or I can write code that actually cares about this problem, even if just to explicitly ignore such files as if they didn't exist. In too many languages the second isn't really an option (which is frustrating if I'd like to write reliable software) or worse, the first isn't an option and so I'm stuck writing endless boilerplate even for a toy or one-shot. The latter is arguably OK if your language is really just for space rockets and medical implants where failure is not an option. But that's never really how things work out.
- lijogdfljk 4y agoYea.. i used Go for 5 years. I just can't agree that the simplicity is true. Yes, the language itself is, but it offloads complexity into my program and thus my day to day is jumping around huge piles of logic which could be made for easier to reason about and understand with some actual help in managing the complexity. Your complex programs aren't easier in Go, in my experience. The simplicity of the language doesn't help me much when my day is spent fighting to figure out how to make a problem which is inherently complex easy to maintain, reason about, and be without bugs. I want a language that makes my day simpler. Where at the end of the day, my "net complexity" is less. Go leaves all the complexity to you and offers you very few tools to solve this. Bugs, spread out logic, and even runtime costs of the overuse of Interface{} (prior to Generics at least) left me with a lot of things to solve myself. My days in aggregate were more complex with Go. Just my experiences.
- mcronce 4y ago> runtime costs of the overuse of Interface{} (prior to Generics at least) Generics aren't going to improve this situation - at least not the current iteration of generics :(
- throwaway894345 4y agoIt depends. Things like sorting a slice will be faster, for example. But yeah, the current iteration is a bummer.
- dragonwriter 4y agoGo always seems to be to be designed to be simple for the compiler (which, to be fair, has benefits: fast compilation is useful in a compiled language, to keep code-build-test cycles short) more than the programmer.
- kaba0 4y agoI never really understood this reasoning. To me the ideal thing would be a fast debug-compile mode that barely optimizes and a don’t care how slow release mode that uses every possible optimization for the end result. Rust is plenty interactive with its similar mode of working. Incremental builds are fast.
- astrange 4y agoI am a performance engineer and recommend against this. Optimizations don't really work that well on their own; to get performance you want an ongoing conversation between yourself and the compiler, which you don't get if the compile time is super long. If you do have a really long running superoptimizer discovering things, then you'd want a way to write that back into the code so you don't need to discover it again. Also, most of your program should be at -Os because it's not hot code and the important thing is to stop it from disturbing the fast parts. (Or because the aggressive optimizations actually make it slower. Totally possible with fancy ones like autovectorization.)
- throwaway894345 4y agoGo strives for a balance. It tries to be a fast language without trading off everything else to that end. So it has a GC and really fast builds and it produces machine code that isn't as aggressively optimized as Rust or C++, but it does so much more quickly (as you noted). These are ideal tradeoffs for a huge swath of applications.