For some usecases. For which you can just import Cheney's package, some other or roll your own. Which is Go's point: simple by default.
For what I'm doing with Go I do not need nor want anything more than a string, I do not need a debugger so I don't use Delve, I don't need logging more complex than what the std libs interface offers... So why should I carry all that sort of baggage by default? If you need that stuff, feel free to import the adequate package or use a language that fits your purpose better. IMO Go is better treated as a DSL than a general purpose language, although I think the same of most languages.
There is no other language that fits my purpose better. Does that have to mean Go is perfect? That I have to stop complaining ... even if it means no change will come about? Even if you think it may be perfect but I don't?
I think Go makes a very nice general purpose language. Better than the others I've tried: C#, Java, D, Rust, Dart, Python, Elixir, and more. All have critical flaws that make them worse for my purposes. If another better language comes along I'll switch. In the meantime I'll continue to use it but will complain about the things I wish I could change but don't have the ability to change myself.
>> ...although I think the same of _most_ languages.
Please elaborate on the non-mosts. I likely have missed many in my searches.
My experience is close from yours. Could you briefly describe the critical flaws of each language you listed, that made you choose Go instead? I'm geniously curious.
Elixir: The BEAM runtime, if I'm going to be fair to C# and Java. Elixir is the most elegant language I've seen in years. I really wanted to like it. I purchased all the available books and really dove in. But then I stumbled on the soft spot of number crunching essentially being left out of the language at the lowest level! That's a tough one to get over as a couple applications I have do lots of financial "what if" calculations. Also Phoenix has an annoying list of dependencies (Node???) and a complex configuration compared to Go.
D: I wanted this to be my primary language after reading Andrei's book when it first came out. Unfortunately D wasn't there yet (this was during the shift from D1 to D2). And after D2 solidified as "D" it has has been moving towards memory layout, CTFE, removing garbage collection, and other lower level stuff that I just don't care about. All of my applications are at a business level and dealing with memory and performance optimization is just not something I am ever concerned about.
Rust: Rust sits at an even lower level than D. I really like the higher level ideas and syntax but I absolutely don't want to think about ownership issues. If that part of the language were removed Rust would be pretty ideal. But then it wouldn't be Rust. Manually controlling the ownership process is a core part of the language and would be pretty hard to change.
Python: Bad deployment situation on Windows. But also I've decided I really prefer the compile time type checking. And while I notice the speed issue I can't really say it's a problem for the applications I code. But I do like the blazing speed of Go and the other compile to the machine level languages.
Dart: Hits on most every item on my checklist. But again, a bad deployment situation. And Dart's focus has shifted towards the JavaScript side and away from a general application language and server side language.
Nim: I'll add Nim because it shows so much promise. I've followed Nim for years, support them on Bounty Source, pre-ordered the book, and keep up with progress. However it's got probably close to a year before 1.0 and probably three or four years before it is as production ready as Go is now. But all in all it's shaping up to really hit the sweet spot for business level apps at a compile to binary level.
Honestly, Go has so much going for it that the items I find missing just aren't nearly enough to stop using it. But, for me, it could be so much better with just a half dozen additions. It's frustrating to see it so stagnant after just being born.
Ownership isn't a “low-level” issue. It arises in every program that manipulates ephemeral resources (like network connections), and you have to reason about it, whether the type checker forces you to or not.
> Manually controlling the ownership process is a core part of the language and would be pretty hard to change.
It's actually pretty automatic. You only need to implement each destructor once. Using `finally` or `defer` is what is needlessly manual.
Ideally I'd like the compiler and compiler syntax to fade away as much as possible while coding my applications. Only the domain syntax should remain: the syntax that allows me to turn my thoughts into working code free of any distractions to satisfy the compiler, error handling, etc.
I wasn't talking about memory management, for which garbage collection is indeed an adequate solution. I'm talking about other resources, which aren't as plentiful as memory (e.g., file descriptors) and thus must be reclaimed in an eager and deterministic fashion.
That's interesting for me to read your comment because my requirements are similar to yours (mostly business level apps with some number crunching), and my experience with each of the cited languages is similar too.
Another reason that motivated the switch from Java and Python to Go in my team, was the concurrency and the ability to manage a large number of asynchronous IO while keeping synchronous code.
-- Continuously bring up that something is wrong.
-- Get them to agree that their viewpoint is good but not perfect.
-- Get them to agree that a change wouldn't be bad.
-- Get them to admit that a change might be good.
-- etc.
We're just now finishing the first step the are into the second. We keep going. Fight on soldiers!