This post was a total let down. It was just a rehashing of the same claims from the Go team rather than about various ways to avoid complexity in one’s Go code.
Go does not inherently lead to simpler easier to understand code. The ability to pass pointers between goroutines alone is a simple way to inject a dangerous amount of complexity into a program.
The ability to pass pointers between goroutines alone is a simple way to inject a dangerous amount of complexity into a program.
This is unclear to me. Yes, there are no special rules governing values passed on channels. Following Go’s language design principles of being clean and imperative making the decision to limit channels to supporting non-reference values only would add “surprises” to the language. Yes, it’s possible to introduce side-effects by passing references/pointers. But Go is not a functional language so that’s the expected behaviour. I’m not clear where the “dangerous amount of complexity” come from? Or are they just stating a preference for the functional way (which Go is never going to satisfy)?
Using mutable cells in any language requires a great amount of care. The examples I’ve seen in Go demos is passing pointers around with no great care put into who owns the pointer. Some of the Go code I’ve read involves tossing a pointer around goroutines and just expecting changes to happen but with no clear flow.
So this is not an FP vs imperative argument. It’s a “mutable cells are hard and some basic advice around them probably needs to be codified” argument.
Yes but passing pointers around channels is just one thing. And the language is garbage collected which mitigates that damage a little. Compare to C++, and Go is way better. Compare to Java, where you can only pass around pointers to things, and Go is way better.
This kind of thing does cause complexity problems, but sometimes it’s helpful for performance reasons. Go is about solving real problems, and this does solve a real problem, namely passing large objects like buffers between goroutines. If it was a useless feature, I would agree with you. But coming up with more sophisticated solutions adds complexity. That said, pointer ownership system in Rust is pretty sick, but they are spending a long time getting that right. Go is out the door now. Maybe when Rust gets here it will obsolete Go, we’ll see in X years.
I think you’re responding to a comment I didn’t make. I am saying is that I was hoping such things would be discussed in the linked post. I’m not denying Go has simplicity relative to other languages. But Go, in and of itself, does not guarantee simple programs, which is all this post seems to be saying.
But Go, in and of itself, does not guarantee simple programs, which is all this post seems to be saying.
No reasonable person would interpret the post in this way. To borrow a quote from this excellent post:
Writers use hedges in the vain hope that it will get them off the hook, or at least allow them to plead guilty to a lesser charge, should a critic ever try to prove them wrong. A classic writer, in contrast, counts on the common sense and ordinary charity of his readers, just as in everyday conversation we know when a speaker means in general or all else being equal. If someone tells you that Liz wants to move out of Seattle because it’s a rainy city, you don’t interpret him as claiming that it rains there 24 hours a day, seven days a week, just because he didn’t qualify his statement with relatively rainy or somewhat rainy. Any adversary who is intellectually unscrupulous enough to give the least charitable reading to an unhedged statement will find an opening to attack the writer in a thicket of hedged ones anyway.
Your absolutist interpretation is in the exact same vein as the rain example from that quote. You are being the intellectually unscrupulous adversary. My turn to be intellectually unscrupulous, just for the fun of it!
Go does not inherently lead to simpler easier to understand code.
Simpler. Rephrasing that, you could say that Go does not have additional simplicity relative to other languages.
I’m not denying Go has simplicity relative to other languages.
Now enough of that, because that’s obnoxious nitpicking. Absolutist interpretations sure are silly! Instead, onward towards your intended meaning.
Yes, the post wasn’t a brilliant discussion of the mechanisms in Go that lead to simple code. That is a bit of a let-down. But I did think the part about accidental complexity was an interesting point, and a nice tie in to how Go aims to only have the complexity necessary to solve real problems. In contrast, other languages try to fight complexity with other complex mechanisms, like the IO monad in Haskell or ownership semantics in Rust. Those are both compelling solutions in their own right, but unlike Go they are trying to be perfect (or near-perfect) solutions. Or rather, Go unlike them, is avoiding perfection in favor of simplicity.
This reply is pure masturbation and the two quotes from me are talking about different things. Go is a simpler language than C++. That does not mean Go code is inherently leads to simpler easier to understand code. The first statement is talking about the language itself and the second one is talking about using the language. MIPS assembler is simpler than C++. Solving a problem in MIPS assembler does not inherently lead to simpler easier to understand code.
Regardless of the masturbatory nature of my comment, it’s still unreasonable to conclude the original post claims Go guarantees simple programs. If this were real life and you were talking to the author face to face, I assume you wouldn’t attribute such a ridiculous claim to the author.
Solving a problem in MIPS assembler does not inherently lead to simpler easier to understand code.
Different definitions of simplicity. MIPS is minimal but has a lot of emergent complexity. Go adds complexity (like a GC, builtin data structures) to reduce emergent complexity.
That does not mean Go code is inherently leads to simpler easier to understand code.
More absolutist interpretations. Every feature of any language meant to make things clear can be defeated by a sufficiently incompetent programmer. No language inherently leads to simpler, easier to understand code. It’s about the common case, a “reasonable programmer” much like laws refer to a “reasonable person”. And a “reasonable programmer” will be able to understand a concurrent Go program easier than a concurrent C++ program, given reasonable programs in each language.
I like most of the Go stories here, but this one doesn’t cover anything beyond the existence of the net/http package and compiled binaries.