It is very easy to implement, and leaves a lot of the complexity (null pointers, generics, etc) to the user instead of solving it in the language.
This is a classic example of worse-is-better.
An MIT-style language would be Rust, which indeed struggled to get to v1.0 and Go vs. Rust plays out quite similarly to what worse-is-better would predict.
C won over Lisp, not because “worse is better”, but because the C's advantages over Lisp (performance on cheap machines) were more pronounced than the other way around (“safety” achieved by means of lots of runtime checking - by no means was it possible to statically rule out errors). Lispers fancy their language of choice the pinnacle of computer science, but the falsity of this claim becomes evident under close scrutiny.
> Go vs. Rust plays out quite similarly to what worse-is-better would predict.
I see a brighter future for Rust in the long run, for the following reasons:
First, Go doesn't do enough for the programmer: Haskell and Erlang are safer and easier to use, and have much better parallelism and concurrency stories. What kind of silly value proposition is “safer than C” or “less verbose than Java”? Rust offers something genuinely new: half-assed attempts at “better C++s” have existed for a while, but “safer C++s” haven't.
Second, Rust plays much more nicely with other languages. Rust is no more difficult than C to call from, say, Python. On the other hand, Go seems to be more of an all-or-nothing proposition: “If you want to use Go libraries, use them from applications written in Go.”
Seems like a "boo Go" echo chamber in here, but as someone that moved their entire backend infrastructure to Go, the offering was so compelling it was worth going against common wisdom and actually rewriting huge pieces of infrastructure code. And I'm hardly alone - many huge companies felt the same value proposition and made the same decisions.
Go isn't perfect for many things, but where it's placed itself - among often headless networking infrastructure projects and backends, it's exceedingly good at what it offers.
When I tried Go, things went like this: First, I deliberately wrote a program with a data race, which the data race detector didn't detect. Then, I honestly tried to write a race-free program, and again the data race detector didn't complain. A couple of hours later, I realized that the second program also contained a data race.
And this 'win' is ill defined. Both won on their market. C was great to do what it did, Lisp too. All the research and crazy idea spawned thanks to high level symbolic thinking is still bearing fruit today. It's not a win as in market domination but gene spreading and still being alive too.
I also think Lisp is not truly "better" in the sense "worse-is-better" is ascribing. But if we suspend disbelief - then the Go vs. Rust story matches the one described in "Worse is better".
Perhaps Rust will win out in the end and "worse is better" won't prevail. Despite liking the idea of Rust very much, I don't think it will.
This worldview is overly simplistic. There is no indication that languages ever "win out in the end" and there is no reason to suspect that the industry is not large enough to support healthy ecosystems for both Go and Rust, who, again, are not competitors.
> An MIT-style language would be Rust, which indeed struggled to get to v1.0 and Go vs. Rust plays out quite similarly to what worse-is-better would predict.
Not having to implement a userland OS scheduler, a production-quality garbage collector, and an industrial-strength compiler backend from scratch strikes me as a fairly New Jersey-style approach, don't you think?
(I think this whole "Rust vs. Go" as "MIT vs. New Jersey" argument is pretty silly. There are many factors going into why Go released 1.0 before Rust did, and both communities have consensus that you shouldn't treat Rust vs. Go as a horse race anyway.)
There isn't one language to rule them all. An advantage of Go over Rust is easier tooling due to a simpler language, an advantage of Rust is a richer type system. These are in opposition.
Rust can reuse nearly all C tools like kcov, gdb, perf, valgrind. On top of it, it has a solid set of its own tools. For example it has rustfmt, cargo, rustdoc (having the ability to test your Rust documentation is great).
Only thing it truly misses is a IntelliJ IDE for Rust and possibly a Rust oriented coverage system.
> An advantage of Go over Rust is easier tooling due to a simpler language
I'm curious how "tooling" is easier in Go than in Rust. To my mind, dynamic tooling (instrumentation, profiling, debugging, etc.) is much easier in Rust than in Go, because Rust uses the OS facilities and looks much like native code, while Go's runtime reinvents the world.
This is in fact what we've seen—Rust didn't have to write custom profilers, custom debuggers, language-specific race detectors, and so on, because the native system tools work just fine.
(NB: I'm not saying Go made the wrong decision with a userland scheduler; I'm objecting to the idea that it's somehow simpler to do that. It's much more complex.)
I should have been more specific by tooling. I meant source code manipulation and analysis, go-oracle and goimports are a couple. There's many more in the go community.
Are they useful, I'm not sure. They feel useful but I have little trust in my judgment. When I switched back in the day from VS to emacs I didn't seem to miss all of the refactoring tools VS provided.
A richer type system is not in opposition to good tooling, quite the opposite. Rust's strong type system enables fantastic static analysis, which, for example, obviates the need for anything like Go's data race detector.
Writing tooling for C++ is difficult because of how entangled all the language's features are (and its wonky grammar certainly doesn't help). In addition C++'s type system is probably even weaker than Go's, having inherited a lot of slop from C.
That said, if you're talking about source code formatters, I'm pretty sure that clang-format predates gofmt (and surely clang-format was not the first automatic source code formatter for C++). The coup for Go was that they got the community at large to standardize upon and champion gofmt, which is not something that C++ has ever matched.
I'm thinking more of difficulty in writing rustfmt compared to gofmt. There's other examples like go-oracle or goimports which as far as I know don't have Rust equivalents.
How useful the extra tooling is, I don't really know.
>
I'm thinking more of difficulty in writing rustfmt compared to gofmt.
The extra stuff that rustfmt does stems from the fact that rustfmt wants to aesthetically format code well, matching the style that the community had settled on prior to its introduction (e.g. avoiding long lines, lining up parameters), while gofmt is fine with less aesthetically pleasing code (long lines, all parameters on one line) as long as the implementation of gofmt remains simple. There's nothing stopping anyone from implementing a bare-bones rustfmt in the style of gofmt and trying to push its style onto the community, but Nick had different goals.
You're right, the comparison isn't as valid as I thought, rustfmt has improved impressively since I looked at it last. 'go fix' might be a better comparison, what's the Rust equivalent?
"Go vs. Rust" is not a valuable comparison because Go and Rust have wildly divergent goals and intended use cases. By the same token you could argue that Rust is a worse-is-better Haskell.
It is very easy to implement, and leaves a lot of the complexity (null pointers, generics, etc) to the user instead of solving it in the language.
This is a classic example of worse-is-better.
An MIT-style language would be Rust, which indeed struggled to get to v1.0 and Go vs. Rust plays out quite similarly to what worse-is-better would predict.