To be fair I will probably not use it even if it has generics, at least not if I can avoid it. It will still have nulls, lack sum types, have messed up dependency management and so on. Though in times when I have to use (because it was not in my control), I would rather have them.
You summarised almost perfectly my gripes with Go. Thank you. Just to add one: any type has a "zero values" as a default value, and the compiler doesn't force you to initialize stuff. That single misfeature caused basically all of my grey hair, and I'm still young.
I'm not a stickler for any specific features: it's more about having a group of features that synergize with each other. So far I've not found a language that does this perfectly, but I've found a few that I think do better than Go:
1. Elixir: Pros: Erlang threading model is clearly the best I've come across, expressive syntax, strong data structures and algorithms in standard library. Cons: Slow for some things, anemic standard library for common problem domains, small community.
2. Python: Pros: Strong standard library for common problem domains, supplemented by a strong community set of libraries. Generally intuitive. Cons: Slow for some things, poor threading, inconsistencies in syntax, general dominance of configuration-oriented programming frameworks rather than libraries in the community, types are just not quite strong enough.
3. C#: Pros: strong type system, speed. Cons: dependency injection hell, MS walled garden.
I'd like to add Rust and/or OCaml, to this list, but I don't know either well enough to be confident.
On paper, but it sure doesn't feel like it when trying to use it.
It's nearly impossible to find out which of the umpteen repositories contains the source for the class you're trying to understand, and MSDN won't be of much help. Much of the standard library also has a bunch of decoy source files that only contain signatures and/or mocks, so it's a pain to find the real version.
OmniSharp has a "go-to-source" option, but you only get the real source if it's in the same solution. Otherwise you only get signatures. Try giving Metals[0] or Rust-Analyzer[1] a shot, this stuff is night-and-day.
The official debugger (vsdbg) only works in VS and VSCode (and explicitly not in FOSS builds of VSCode). There is netcoredbg[2], but I still haven't figured out how to convince Emacs to use it. This wouldn't be as much of a problem if the culture wasn't so hostile to printf debugging (for example, ~nobody bothers to implement helpful ToStrings).
There is a heavy cultural bias towards MS libraries, regardless of their merits (ASP.Net Core, DI hell, EFCore, etc). See [3] for an.. interesting example.
OmniSharp has a habit of giving up randomly, giving useless error messages, and most GH issues consist of people repeating "+1", until there is a one-liner about how an update fixed it. Root cause analysis, what's that?
> It's nearly impossible to find out which of the umpteen repositories contains the source for the class you're trying to understand
> OmniSharp has a "go-to-source" option, but you only get the real source if it's in the same solution.
I have to admit I almost never run into this issue because because I don't really care what the source of the standard library does, the docs have always been sufficient for me. You could try https://source.dot.net/ though.
In the very rare case I do want to see the source of some 3rd party code I use dnSpy. It isn't as nicely integrated, but it's a very nice decompiler and debugger.
Hm, I didn't realize .NET Core had been changed to an MIT license. That wasn't the case when I was working in C# on a regular basis.
My guess is that MS proprietary tooling still sucks out the air from FOSS tools, but I can't speak from experience there so I'll just admit I don't know how the ecosystem has changed since I worked in it.
Visual Studio is definitely still the ideal environment for writing C#, but JetBrains Rider is a solid alternative, and VS Code with the right set of extensions is probably "good enough" for most things.
A language can't be everything to everyone. Given its age it is very widely used. So I'm not sure the lack of genetics is really hurting adoption. You run the risk of driving away existing users but not attracting people that already wrote the language off.
I say this as someone that doesn't use it for similar reasons as you. But I have ran into the above trap before.
The thing is, for people who want generics, sum types, non-nullability etc, there are plenty of other languages to choose from. For those who specifically want a simple language, Go is (was?) one of very few options.
Sure they are. Sum types usually mean a pattern matching syntax, destructuring, and a different declaration syntax. Rust’s match keyword, for example, is a powerful construct covering guards, destructuring, and different types of binding. Non-nullability requires generics for a result type which is a huge source of complexity. Generics impact parsing, code gen and runtime efficiency.
1) Non nullability can be implemented in language without generics, and for all types instead of just pointer types. That can be used to enforce null checking with pattern like:
if let var_name = nullable_var {
// use var_name as non nullable
} else {
// nullable_var in null, handle null case
}
And any tagged union can be reduced to nullable of member type without pattern matching, with some specific syntax. It is not hard with an imperative language.
2) Without generics, you are probably reinventing the same code, or using reflection which is not even type safe, or worse, using code generation. For instance D has generics AND good compile times. I guess Nim compiles fairly well too. Or you can choose partially type erasure based generics with a different tradeoff. There is no point in not having useful generic functions on generic data structures in a language that came in 2000s.
Once write Python or ruby or something and come back to Go. People without knowledge of other languages with generics tend to think you are writing for loop in while loop in if - else break monstrosity because native compilation and performance come with a cost in expressiveness, while it need not be.
Off the top of my head: Poor error messages, any type checking is run on the generated code so harder to enforce properties, and if code generation is not in-language, then the base logic can diverge for different types, which is bad when you find bugs.
>Non-nullability requires generics for a result type which is a huge source of complexity. Generics impact parsing, code gen and runtime efficiency.
The C# 8.0 approach to non-nullability doesn't require generics at all (though C# already has a robust generic system). They just made reference types work the same as value types, add a ? if you want it nullable, otherwise it isn't.
I think Rust's way of doing it with Option is probably a better way, but C#'s way of doing it is definitely more accessible to the average programmer.
You could have a very simple `match` with no nested patterns or guards, like Haskell's core language.
> Non-nullability requires generics for a result type which is a huge source of complexity.
Option could be another built-in generic like Map in Go. Or one could simply have to write a new Option type ever time. Sucks, but aren't go programmers used to this sort of thing?
I'm sure that being backed by the largest software/advertising company in the world has nothing to do with its adoption rate, and that popularity is a direct mapping of quality of a programming language.
The Google backing and hype kept me away from Go for years. After being stuck with a succession of scripting languages that weren't doing it for me and being frustrated at the time it takes to be as productive in something like c, Go is really the sweet spot of readability, reliability and productivity for me. I think the Google backing may not be as advantageous as some people think. Dart did not become a popular language and would probably have died out if Flutter hadn't come along.
Yeah, Go being from Google is not necessarily a good thing. It means the language is under the control of a single company and, what's more, a company that is well-known for giving up on many of its projects.
And the open-source aspect of Go's development is managed entirely in Google services (the dev mailing list is a Google Group, you can't contribute without a Gmail address...the list is long). Sure it's hosted on GitHub, but the majority of the real conversations are elsewhere.
I guess the political wars of JavaScript vs Dart, ChromiumVM and Chrome team dropping Dart on the floor, causing the departure of the original design team, kind of helped to Dart's success.
The political wars at Google with Dart are quite visible from outside, with Fuchsia picking up Flutter, and strangely the future of Android UI looks pretty much like Flutter, after too many times asking Android team about what was their opinion on Flutter for Android development at IO Fireside, meanwhile the developers' survey has had questions about how much we cared to see it supported on Kotlin multi-platform.
So yeah, had Chrome decided to push Chromium VM no matter what, Dart would be as successful as Go by now, after all younger generations don't seem to have any problem being Chrome developers.
Java has genetics and it is many times more popular than Go. I'm not sure absolute adoption of Go is a good way of divining programmers opinions on genetics.
Oh, I'm not by any means saying it's the most popular language. I'm just comparing strictly based on the comment, people who like go vs people who will never use it because of its lack of generics.
I wonder if there is more of people like me or people like you...