> If you're looking to reduce the whole discourse to "X vs Y", let it be "serde vs crossing your fingers and hoping user input is well-formed". It is one of the better reductions of the problem: it really is "specifying behavior that should be allowed (and rejecting everything else)" vs "manually checking that everything is fine in a thousand tiny steps", which inevitably results in missed combinations because the human brain is not designed to hold graphs that big.
My pet theory is that this corresponds to the "two cultures" of software engineering: do you value up-front work and abstraction to reduce cognitive load and debugging, or would you rather (try to) pay more attention and spend more time debugging to reduce how much you have to learn and think up-front? Go seems pretty firmly in the latter camp. That's exactly why I am not interested in the language either, despite the various things it gets right.
It’s easy to argue against boilerplate: just find an example where a particular language feature shines and show that it reduces amount of code. Less noise reduces risk of human oversight. Arguing against complexity is much harder, similar to arguing against a suffocating bureaucracy: the cost is much more deferred, global, and often is only evident when it’s too late. Death by a thousand paper cuts.
And even with the most elaborate type acrobatics, we still have to validate things “manually”, so we need a “standard process” anyway. So while reducing boilerplate can be worthwhile, it’s not sufficient.
In order to argue language complexity, imo, you need truly compelling and recurring real-world examples. Rust strikes many heavy-weight birds here, but has some sources of immense complexity that yield very meager returns, like async Send, Sync, Pin gymnastics and function coloring. Go otoh suffers some very repetitive boilerplate, like the `if err != nil` 3-liner, for instance, which was elegantly solved in Rust with `?` etc.
None of those real irritations are addressed in this article, which seems to be an extended complaint that Go isn't as portable between Linux and Windows as the author would like it to be. If you're unfamiliar with Go and attempting to evaluate the language, there's not much in here that I could recommend one way or the other. You would be better spending the time on doing the Tour of Go, then reading one of the various "pitfalls" articles.
I don't think that's true. The author is using that lack of portability as an example of what they think is wrong with Go:
> And they're symptomatic of the problems with "the Go way" in general. The Go way is to half-ass things.
> The Go way is to patch things up until they sorta kinda work, in the name of simplicity.
And I get the point they're making. The issue isn't that file permissions don't work consistently cross-platform in Go, it's that they can't work consistently cross-platform in anything but rather than add complexity Go has papered over the cracks. If that's an acceptable approach in a core file API who knows how often it's employed elsewhere in the runtime? The following section the post shows this mindset as implemented in monotime and the many potential footguns the official implementation introduces.
Interestingly enough, C of all languages had enough sense to not require permissions as an argument for fopen(3).
Start at welcome_controller.go and follow the flow. Notice no structs for the sake of structs I make heavy use of map[string]any which serializes to json so nicely without any `json` modifiers.
I'm really glad I got off that ride.
I feel like its an unfortunate consequence of having a good package manager which encourages proliferation of too many very small dependencies.
I was playing with some Rust-based blockchain system, and the number of external dependencies pulled in (recursively) to build the code truly amazed me.
I don't really know, but I'm guessing that a similar C++ project would have required many fewer dependencies.
Maybe a C++ code base would tend rely on a small number of big libraries?
Or maybe a C++ code base would (for some reason) be more inclined to use binary libraries provided by already-installed Debian packages?
Sometimes I see single-header libraries you can just drop in, other times I see large Cmake projects that you add as a dependency to compile when your project compiles.
I've never seen the kind of dependency chaining that languages like JS or Go show.
* It's a specialized tool not suitable for all (or even most) projects
* It needs a bit more time to both develop as a language and ecosystem
But it's clear that it's not half-assed and a lot of thought went into it.
Interesting to hear about Go's development as well. It was starting to pick up when I was in college, and now it's had a few more years. Bit disappointing to see it's so messy.
That is, by far, my biggest pet peeve with the language.
Most languages have try/catch patterns, but Go opted for multivariate returns and a discrete error type...without pattern matching!
At least 20% of Golang code I look at is the if err != nil pattern, which is a crazy amount of repetitive boilerplate. I don't think the must pattern is a good alternative either in many cases.
[1] https://medium.com/@divan/how-to-complain-about-go-349013e06...
This opinionation runs deep into the Kubernetes ecosystem as well (one of, if not the, biggest Golang project out there).
Here is an example: https://github.com/kubernetes/kubernetes/issues/53533
This account has enough karma for flagging, and I can see the title of this submission is prefixed with [Flagged] but I don't have an option to Vouch.
How does that work? I flag/vouch pretty rarely so I'm not always sure.
So what? If you don't use it as intended, it might not do what you want. Don't use it on unsupported niche operating systems.