more code has been written in Go than Haskell, Rust and Ocaml combined.
Powerful languages let you grapple with problems, weak languages first make you grapple with the language before tackling problems. Some people feel like Go gets in the way. I have not written any Go, but I understand both the praise and the criticism.
Powerful languages can cause other issues, but they do enable certain things that weaker languages simply never can.
[Citation needed]
I don't see why that would be true. In my experience, the most expressive languages often produce the most impenetrable spaghetti code. Can you explain your reasoning?
In a language with lenses, you can delimit where your models are mutated. In a language that lets you treat composable effects in a generic way, you can e.g. split up your variables explicitly with ReaderWriterState, making it clearer which serves which purpose.
The kind of things you might be tempted to use "magic" or global variables for in a lesser language - the "cross-cutting concerns" - you can instead handle in normal code as a generic kind of context. E.g. an audit trail can just be Writer. Or actions that need access to a database session can just be another kind of context. I'm working on such a thing right now (see tpolecat's doobie for a public example of the same kind of thing) - whether a function accesses the database or not is visible right in its type, but it's easy to compose functions that do. The types ripple up, and in the end I'm probably going to do session-creation-in-view - but in a principled way, using the ordinary type system, visible in the code - with Spray, my web route definitions are just another ordinary bit of Scala code (whereas in most languages I would define routes in an external config file, or at best a config object a la Django - adding complexity).
Heck, error handling is a perfectly good example of this. In a less expressive language, the only way around the boilerplate of handling errors where they occur is unchecked exceptions (or effectively-unchecked exceptions, as in "throws Exception"). In a language with good generic context support, the possibility of failure is just another kind of context that we compose with the same generic tools as any other, and the control flow becomes something sensible again.
Simple languages led to complex code bases.
Many of the Enterprise Java sins were caused by the language limitations and developers trying to work around them.
Anyway Go has its use cases, and it is already an improvement if less C code gets written.
I have seen this happen in C codebases before Java took the enterprise.
Its own little macro based DSL and pointers that were actually handles for the real data.
I'm repeating myself here, but: A Haskell user and a Lisp user are both sure that they're at the top of the power curve, and they're both sure that they're looking down when they're looking at the other language, and they can both tell you precisely why they're sure they're looking down ("It doesn't even have a decent type system" and "It doesn't even have macros", respectively). But they can't both be looking down. What's wrong here?
What's wrong is the assumption that all languages can be ranked by a one-dimensional attribute called "power".
Or look at it another way: Power? Power for what? Well, for writing programs. But what kind of programs? General programs? I've never written a general program in my life; I've only written specific ones. Then "power" is whatever's going to make it easier to write the program I need to write. Whatever language does that is the "most powerful" language for the problem I'm facing.
What power is Go shooting for? It's the power to write a ten-million-line application and have it be maintainable for two or three decades. (That's not my guess; it's what Rob Pike said the language goals are.) If you face that kind of problem, Go may in fact be a very powerful language.