Here's a hot take from a polyglot who does a fair bit of professional work in Go:
Go is a low-blub language whose advocates are proud of the fact that they never made it past 200-level CS courses. It's the computing equivalent of the blue-collar anti-intellectualism that is rampant in politics these days.
Yes, Go the language is simple - it pushes complexity off to your programs instead! Instead of functional expressions, Go programs are pages and pages of iterative loops and variable manipulation. Without generics, you can't use even the most basic functional constructs like map and reduce. The most boring mainstream languages like Java and Javascript are adopting functional paradigms, whereas Go is actively hostile to functional programming.
Nothing is more tiresome than the continuous prattle about exceptions. "How can you possibly write code that is robust in the presence of errors when you don’t know which statements could throw an exception?" Easily. That's the great thing about exceptions, you don't need to know about them to write robust code.
In general business processing, an exception thrown across a transaction boundary rolls back the transaction. In most cases that's pretty much all you need to know. In the case where you need to explicitly rollback a state change (extraordinarily rare in business processing), you add a try/catch/throw, and you don't even need to look at the exception!
The fact is, 99% of programs need only one exception handler. In webapps, it's the http processor that returns a 500 error. In GUI apps, it's the main execution loop that shows an error dialog.
Go's error handling not only requires endless tedious "if err != nil return err", but each one of those statements destroys stack information. Folks like to berate Java for long stacktraces, but those stack frames are valuable for debugging. By comparison, Go's errors are an opaque bit of text. Third-party libraries can help by wrapping errors in other errors (hand-building stacktraces), but this won't help you when using third-party libraries that don't use these wrappers.
I'll say something positive about Go, and why I still use it: It's a better C. For low-level-ish code that needs performance and fast startup time (CLIs, simple GAE services that scale to 0 and need immediate startup), Go fits the bill. Having concurrency built into the language is nice, although most other common languages have equivalent facilities in their libraries.
But as a language to take over the world: Not a chance.
Please review the site guidelines and, when commenting on HN, do so more in their spirit. We don't want programming language flamewars here, especially after seeing what they did to other communities.
> whose advocates are proud of the fact that they never made it past 200-level CS courses.
I agree with many of your points but is this kind of generalized ad hominem really necessary? There are many people (myself included) who don’t have CS degrees yet are still capable developers and programmers. I don’t see how criticizing someone’s lack of a formal CS education has anything to do with criticisms about Go as a language.
It's a deliberately provocative comment to be sure. But I'm not trying to demean people who don't have CS degrees, just the ones that are proud of it.
The Go community puts out a lot of smug articles like the OP bashing other languages for having features that Go lacks. Inside the community it's largely an echo chamber. When this stuff hits the broader community, I want pushback.
Just a tip, code formatting does not work well for quotes because it often leads to unnecessary horizontal scrolling (especially on mobile). A common convention here is to use a leading > character and italicize the quote by enclosing it in asterisks, like this:
> *This quote can be any length without horizontal scrolling*
which renders as:
> This quote can be any length without horizontal scrolling
Update: Thanks for making that edit. Much easier to read on mobile now!
Someone had to say it. My first impression of Go was that its creators have not worked on a modern, large scale system in decades. And they probably have not. Go skips about 40 years of advances in language design and code maintenance. We have stack traces for a reason. We have exceptions for a reason.
We came to it as software has become more complicated. The fact that you have to assemble the path to the root cause of an error yourself is completely bonkers.
Are you sure about this?? Go is being used to build some of the most important software in devops and databases today. Maybe its the thinking thats different but certainly it doesn't make codebases complex by itself.
Like Terraform? Yes, so? That doesn't change my opinion. It takes serious experience and skill to write good Go code and tests at scale. I don't really understand why people claim that Go is a simple and straight-forward language. For a "Hello, World", maybe, but once you hit the gotchas, the fun begins.
It can be difficult to reconcile comments like this with the reality that Go was designed at Google to address difficulties developing large-scale applications and even Kubernetes is written in it.
I agree with many criticisms of the language but sometimes that criticism seems to enter its own sort of echo chamber.
I don't get the impression that's a conclusion you came to on your own, and I don't find what is essentially hearsay or gossip to have a very high information signal in general.
That boils down to Go needing generics, which I agree with. I don't think we're completely in disagreement. I'm just skeptical that the language is quite as bad as you're sort of suggesting. That article falls short of condemning the k8s codebase and instead just says it could be better with generics.
To be clear I'm not the person who stated K8s has a garbage codebase or whatever. I was just linking relevant material (and I should have clarified that in my post instead of drive-by posting - sorry, was distracted).
this is an unnecessarily divisive take from a "polyglot" (read: software engineer) who admits that Go has its place in a software engineer's toolkit. It seems that you're attacking a straw man who believes that Go should be the only language that exists, and is the right choice for every application? Who argues this?
I find it's the strawman that many (most?) Go "opponents¹" respond to.
Every language has its die-hard cult of a few who claim it should be the one and true only language in the world (and the claim is always wrong). But Go is the only case I know where I see people actually respond to that. As if it were a real question.
I think it's a combination of many aspects:
- Go is quite opinionated as a technical object, thus polarizing; which attracts more contentious debate(-rs) than average.
- In truth, Go was meant to be niche, and wants to remain so; it never actually tried to become as big as it is. The whole "take over the world" mantra is pretty much alien to its core design, its primary intent and, most likely, ultimate destination.
- Go has a few powerful traits (great at concurrency, great at scaling simple services, etc.), but people want to generalize, and indeed Go's not far from being quite more general (if it had generics, etc). There's no consensus as it's arguably hard to bring in more expressiveness while preserving the intricate mechanics of its elementary objects (each must respond to all others properly). This "in flux" situation has passionate advocates on all contentious sides.
- Google's weight behind Go makes it feared by some, but it's not like Google is trying to make Go "the one and only", even internally (that proposition doesn't make any engineering sense).
- Some hype, by 'influencers' in the space who fell in love with it, made Go a shining beacon of something— this elegance in simple abstractions (when it fits one's problem space well), its manageability by teams, ease of programming, etc. There's something to be said for these qualities, but again it was just wrong to generalize... it's just what people do. We move in cycle of hypes, trend-waves, it's best to keep a Bayesian mind through all of it.
So much ado about a niche.
[1]: wth with that even being a thing, it's a programming language for Turing's sake. Let us recall that languages are neither good nor bad, but shit-posting makes it so. Yes, even Rust: neither holy nor evil, I assure you.
What are your thoughts of Ada/SPARK as a replacement of C? In my opinion it is a better C. At times I wish it were not so verbose but I consider it a feature. It has everything you mentioned that made Go fit the bill, and so much more that makes it even better at both low-level programming and high-level programming. My main and only problem with Ada is that it lacks libraries, it needs a more vibrant community. This can be changed though!
As someone who fits this description "never made it past 200-level CS courses" how do I make the leap from interpreted basically procedural programming to a compiled language like Go, or C, or whatever else - the mental model seems very very different to me, and I have trouble understanding what the program is doing when I try to just read along.
My advice is to ignore gatekeepers like OP and just start playing around with Go. The Go Playground is a great place to start, you can run it right in your browser. https://tour.golang.org/welcome/1
You can try Pascal. I switched from BASIC to Pascal 30 years ago then to C 5 years later. And even though C has been my everyday language for 2.5 decades for all my projects, Pascal was still the one that provided me the most natural mental model and that was the easiest to learn by practicing without lessons. I used to code as I thought without being interrupted thinking about stupid stuff like "I need a buffer to store this argument and to verify its length, ah shit I then need the ability to return an error if it's too large". In TP7 you even had "break" and "continue" statements that were missing from previous ones, that made it closer to C and a real joy to work with. The code was quite clean and extremely readable even with few comments.
The lower you get the more your model of computation must understand the host system; but be careful, even C statements often compile into surprisingly unexpected machine code.
If you want to explore this route I recommend picking up an embedded hobby project; Ie grab an Odroid Go and write some fun little arduino games in C++ using the Esp-Idf toolkit. It's got two cores, some IO, and a slowish LCD; and so you'll have to understand async programming and have a mental model of the device's memory to get any satisfaction.
But that still doesn't require much beyond most 200 level computing knowledge. :)
I think you are going in the opposite direction to which the OP seems to be lamenting.
First of all Go is not C; it’s much much easier to learn and write production grade services easily. There are a ton of free/ online resources to learn go; I’m self taught and have written production code in go for the past several years with no formal training. The godocs are great; YouTube has videos from gophercon and other conferences as well.
Second: OP is lamenting the lack of higher order programming paradigms like Generics; If you’re using an interpreted language it likely already has support for those things.
Ingenuity in code for solving real problems is great. Often times I’ve seen those who know a language deeply write code in ways that makes it remarkably hard to read. Mostly it’s because language features are used in unexpected ways which the author feels is great for x reason, but reduces readability.
With Go, it’s actually really hard to write opaque code like that since the language is so laser focused on low level primitives. And honestly... for core systems, I think that’s an incredibly good thing to have.
>Go is a low-blub language whose advocates are proud of the fact that they never made it past 200-level CS courses. It's the computing equivalent of the blue-collar anti-intellectualism that is rampant in politics these days.
But there is, and has for a long time been, a push for blue-collar "coding" jobs, because highly educated programmers are expensive. It dovetails especially well with the mentality where only the next quarter results matter, and software is a cost center, which is a lot of places.
Go is popular for the same reason PHP is popular, or why $0.99 goods are sold in huge quantities despite their quality.
To be fair, the implementation of the Go compiler and runtime is done by real experts, and is impressive. I suppose that nothing in Go is done by ignorance; everything is a conscious choice, to meet the bottom line: a person can learn enough Go in a weekend to be immediately productive.
> The fact is, 99% of programs need only one exception handler.
Maybe if you just write high level business logic and something else already handles exceptions for you. I think my Java code typically has 70% of the exceptions handlers that I also would need in Go. Need to close upstream connections, release resources like buffers, etc. If it’s not catch blocks, then it’s at least a finally block. And often it’s also a good idea to catch and transform an exception, so that the calling code doesn’t need to deal with exceptions that come from pure implementation details.
The parent implied that in exception based languages you can save all the boilerplate since exceptions just propagate. My statement here was that I don’t think this is true, since you still need to do error handling (and have error awareness), eg for resource cleanup during those.
I am very aware about try with resources. It works however only if the lifetime of objects are tied to a scope.
* The overwhelming vast majority of functions do not allocate resources that need to be explicitly cleaned up.
* Cleanup is no more painful with exceptions - try/finally is not materially different from defer.
* In any language, a healthy pattern is "if you allocate it, you clean it up". This pattern in Go and Java looks basically the same.
* Go's lack of exceptions mean that you pay the penalty of error handling on every function call, not just in the tiny fraction of a fraction of a percentage of function calls that allocate resources.
* For business processing... this is just a non-issue, full stop. There's generally only one resource that gets allocated - a transaction - and it gets cleaned up automatically on exceptions. All that noise in Go is an utter waste of time.
Much of your complaints simply do not apply to many use cases for people when developing a server side web application. Just because Go does not have such features you are used to using in your high level language does not make Go a bad language. I also find it funny that you dislike the simplicity of the language because it apparently empowers "blue collar" types (uhk, how gross!) to do the jobs you are used to doing.
Did you just call Rob Pike, et. al idiots, dumb, and landing-on-the-moon-denying Trump supporters?[1]
Thanks for the good laugh. I like the simplicity. I like that it shuns the insane nested psycho-babble that heavily OOP natured codebases can get into.
[1] I am joking, but only to prove a point. Rob Pike is not some CS drop out.
Go is a low-blub language whose advocates are proud of the fact that they never made it past 200-level CS courses. It's the computing equivalent of the blue-collar anti-intellectualism that is rampant in politics these days.
Yes, Go the language is simple - it pushes complexity off to your programs instead! Instead of functional expressions, Go programs are pages and pages of iterative loops and variable manipulation. Without generics, you can't use even the most basic functional constructs like map and reduce. The most boring mainstream languages like Java and Javascript are adopting functional paradigms, whereas Go is actively hostile to functional programming.
Nothing is more tiresome than the continuous prattle about exceptions. "How can you possibly write code that is robust in the presence of errors when you don’t know which statements could throw an exception?" Easily. That's the great thing about exceptions, you don't need to know about them to write robust code.
In general business processing, an exception thrown across a transaction boundary rolls back the transaction. In most cases that's pretty much all you need to know. In the case where you need to explicitly rollback a state change (extraordinarily rare in business processing), you add a try/catch/throw, and you don't even need to look at the exception!
The fact is, 99% of programs need only one exception handler. In webapps, it's the http processor that returns a 500 error. In GUI apps, it's the main execution loop that shows an error dialog.
Go's error handling not only requires endless tedious "if err != nil return err", but each one of those statements destroys stack information. Folks like to berate Java for long stacktraces, but those stack frames are valuable for debugging. By comparison, Go's errors are an opaque bit of text. Third-party libraries can help by wrapping errors in other errors (hand-building stacktraces), but this won't help you when using third-party libraries that don't use these wrappers.
I'll say something positive about Go, and why I still use it: It's a better C. For low-level-ish code that needs performance and fast startup time (CLIs, simple GAE services that scale to 0 and need immediate startup), Go fits the bill. Having concurrency built into the language is nice, although most other common languages have equivalent facilities in their libraries.
But as a language to take over the world: Not a chance.