Hacker News new | past | comments | ask | show | jobs | submit login
Why Go gets criticized so much (npf.io)
122 points by jorgecastillo on April 8, 2016 | hide | past | favorite | 236 comments

I don't hate Go. I do strongly dislike posts with clickbaity titles that have an admission the title is wrong in the very first sentence.

The rest of the article is little better. It can be summed up in one line: People who dislike Go are upset because they incorporated their favourite programming language into their identity, and the success of Go challenges their own choices.

Although I don't hate Go, I also don't like Go much, but it's not because it challenges my identity. I am not a Haskell or Scala programmer. I've used a whole bunch of languages in recent years, none of which are especially clever. I dislike Go because I agree with the criticisms of it and I'm afraid I might end up having to maintain code written in it one day. That wouldn't be much fun.

Fortunately, so far I've been able to avoid maintaining PHP or COBOL so hopefully my luck will hold and I'll be able to dodge Go too.

Yes, that title shouldn't have been posted to HN (see https://news.ycombinator.com/newsguidelines.html) and we've changed it accordingly. If anybody suggests a better title, we can change it again.

I am not agreeing with your sentiment for Go but I do want to strongly agree with this statement:

> I'm afraid I might end up having to maintain code written in it one day

I have similar fears about Ruby. This is also true of many contractor firms where they write beautiful tested code which is designed to work really well right now, but not designed to last (think views rendering database objects).

I think this is a sentiment people need to have when they see something cool or some sort of solution: Will I, in 4 years, want to maintain this? Will some person, in 4 years, curse my name for having written this?

I think python is going to keep eating ruby's lunch as more universities teach it.

I don't dislike Go. I just think there are zero use cases where Go is the best choice. But what I do dislike is when people try to hype and con others into adopting a language to justify and increase the return on their own time investment.

> But what I do dislike is when people try to hype and con others into adopting a language to justify and increase the return on their own time investment.

The same can be said of any programming language community, IMHO.

True. This is why I find the point of the post kind of "backward". I don't think most people hate something because they feel attacked in their identity. I feel like it's the opposite: most people defend a certain technology at all cost because they feel attacked in their identity when somebody criticizes it.

Sure. I think it's more prevalent among Go zealots, probably because so many were lured into it by the inital hype, but it's not at all Go-specific. Another example is the hype and love-hate relationship people have with Javascript MVC frameworks. Even with React, which actually deserve the hype, there are many who default to "hating" it because they're sick of being fooled by all the hype.

I agree the title's a bit baity.

But this part stuck out for me:

> When I first heard about Go, I thought "What? No exceptions? Pass."

Lo about 12-13 years ago I balked at Python's significant whitespace, but I came around. And rust's lack of exceptions, but I'm coming around. I think there's certainly something to be said for "identity" (maybe it makes more sense to describe it as prejudice/bias/context, but whatever).

I haven't given Go a fair eval yet so I can't say much (except I don't "hate" it.)

"I dislike Go because I agree with the criticisms of it and I'm afraid I might end up having to maintain code written in it one day"


"I also don't like Go much, but it's not because it challenges my identity"

You are EXACTLY who the article is talking about. One of Go's selling points is maintainability. Go's inherent bias towards maintainability challenges your identity.

Selling points are not facts, they're just arguments people who are trying to sell something like to make.

Go's users and designers make all sorts of claims about it. As it happens, I've evaluated them and find that I often disagree with them.

For instance, Go projects often don't specify the versions of their dependencies and choose to just clone the code into their own source tree instead - if you're lucky. If you aren't then the project simply depends on whatever is found in the dependencies git master branch. I find this to be poor practice from several perspectives, maintainability amongst them.

"Selling points are not facts"

except when talking about maintainability, you are not talking about facts. Show me the "fact" that Go is hard to maintain.

I never said code written in Go is hard to maintain. I said I don't want to maintain it, because I don't want to debug or write Go myself. You're arguing with a straw man.

the article is suggesting that when people say they don't want to debug or write in Go is because it challenges their previously formed beliefs in what they believe they need from a language. The fact that there may be another way or that projects are increasingly succeeding, challenges their identity.

Counterpoint: Show the fact that Go is easy to maintain.

The language is, honestly, too young to have much "rubber meets the road" legacy code for anyone to make a strong evidential case with. It's all theory until a decade from now.

The burden of proof is on the people making the "selling points" to prove that they are true -- in this case, if the Go community claim that Go is easy to maintain, the burden of proof should be on them.

(Note: I'm not arguing for or against this point; I've never used Go, so couldn't possibly know)

Isn't that fairly subjective? Some people find Lisp hard to parse and therefore to maintain but that doesn't mean it's inherently unmaintainable.

Yes totally subjective - different people work on different projects which eventually opinions are formed from.

I don't think Go was intended to improve upon any Lisp deficiency.

If that's an accurate summary (I am not commenting on that fact), it's a completely clickbaity summary. Because it applies equally to why everyone hates every even semi-popular language (other than their one true love, if it's considered sufficiently popular).

For a one line summary, it's pretty accurate, but it's also a great illustration of why basing opinions on one line summaries is often a bad idea.

The difference between Go and pretty much every other semi-popular language is that Go is very much defined by what it isn't rather than by what it is. In that way, its success is an implicit criticism of other languages much more than the success of any other language would be.

What's worse, is that it's a criticism backed up by empirical data. But programmers are unique and lucky, in that they get to be illogical and dogmatic while getting to appear rational and technological.

Bad code is bad code regardless of language. Some languages just make writing bad code more palpable than others.

If the engineer who wrote the code understood the problem well and was a decent engineer, then the code will be maintainable no matter what the language is. Understanding the problem well is very rarely achieved.

The issue is not "is the code maintainable" or "does Go lead to unmaintainable code".

The issue is, do I wish to spend my days debugging code and writing more code, in Go? I used languages with Go's limitations back in the 1990's. I don't want to go back.

Writing and debugging code in Go is extremely more pleasurable than debugging, say, python. I write Go all day while our data scientists write python. Unfortunately python gives those guys enough rope to hang themselves and me too. It's simply harder (not impossible of course) to write unmaintainable code in a limited, static language like go.

Python in a nutshell: What you gain in flexibility and terseness, you more than lose in needing 100% unit test coverage, because every line could fail to execute (with an error that many other languages would find at compile time).

Yeah, I wouldn't want to maintain a large Python codebase either.

Disclaimer: I work at El Goog.

I recently moved teams so that I could use Go exclusively. It's often been said that Go solves the problems Google developers have, and it's 110% true. It's much easier to get things working, and it's much easier to write things like Protocol Buffers. But the key for me is that Go isn't fun in the sense of "wow, I'm so smart that I managed to one line this thing", it's fun in the "wow I read this code and I can understand what's happening and hack on it to do something else."

I've worked on teams with monolithic Java code, and it's nigh-on impossible to understand what's happening and where you are in the logic flow. I don't have that problem in Go. I even delve into the standard libraries to see how the original Go devs did something, and I both understand it and think it looks like code I would have written too. I never get that feeling from any other language, where I feel like the standard libs are written by hyper-intelligent aliens.

When I exclaimed this internally, I got the sarky comment "It's almost as if the things Go leaves out makes it easier". And that's the core of it. Would I like generics? Sure; I do miss map(). But that's it.

Go is opinionated. People that don't like Go don't share the opinion. That's OK. It's taken me a long time to realize there is no One True Language that can do everything (it was soon after steveklabnik said something along the lines of "I don't know why you'd want to write a web app in Rust"). Once you get there, you won't hate Go anymore, nor indeed any other language.

Apart from C++. Screw that ;)

The reason Google's Java codebase is impossible to understand is not the language, it's mindless application of 'best practices' like dependency injection on an industrial scale. Guice is open source, anyone can go look at it. Just imagine a big complex server in which the "new" keyword wasn't used anywhere because everything was handled by the dependency injector. You get these things:

1. Things that should be compile time errors turning into runtime errors.

2. An IDE that can't navigate anywhere or usefully analyze the code because everything has interfaces between it.

3. Things being mocked out in unit tests just because they can be, meaning lots of superfluous code and tests that pass when they should fail.

There's nothing about Java that mandates this style of programming. It's the result of years of programmers trying to be clever and finding ways to do things better without being sufficiently cynical about new trends and fashions. Given that Java is 20 years old, there has been plenty of time for people to find ways of making simple things complicated.

Go will suffer this phenomenon too because it's not to do with the languages themselves, it's to do with programmers who have safe corporate jobs finding ways to make themselves stand out from the pack by inventing and spreading 'best practices'. If anything, Go will suffer it worse, because the language itself is so limited, so there's more potential for bizarre hacks disguised as cleverness. Like that Go profiler that worked by rewriting source code to insert stuff between every single line of code.

You are predicting the future (of Go) based on the past (of Java).

Non-idiomatic Go (or as you call it "bizarre hacks disguised as cleverness") is frowned upon. One example that comes to mind is the Martini web framework[1], which, once pointed out, resulted in a rewrite[2].

[1] https://github.com/go-martini/martini [2] https://codegangsta.io/blog/2014/05/19/my-thoughts-on-martin...

Non-idiomatic code is frowned on by all programmers working in every language.

The problems start when the "ma" is dropped from idiomatic. There's nothing in the design of any language that can stop people coming up with idioms and ideas that sound clever and become widely adopted but which actually cause problems down the line. Go is not immune to this. I'd argue Go is largely composed of such things to start with!

Very recently I have begun to work as programmer, and having to work with PHP I looked at phpunit and unit testing (first time I do it semi-seriously). The guidelines for mocking that I have found are about dependency injection (phpunit has some helpers, but I think that's it).

What is the alternative to it?

Python has an alternative: to use a technique called "patching". Basically, in Python, every module is just an object you can access, so in your unit-test, you can easily go into that module, replace a symbol inside a module (or a class) for something else, run unit-test, put thing back. Very nice feature which gives you incredible power to not have to code "with tests in mind".

The problem isn't with the idea of using mocks in testing. The problems start, as often the case, when people start religiously applying a design pattern and end up over using or abusing it.

The problematic thought process goes like this:

1. Gee, my tests are really slow and flaky and hard to run because they talk directly to a database. I know! I'll swap out my real database connection with an in memory database.

2. Things are better, but they're still slower than I'd like. Maybe I can just write a wrapper around my database code, make it implement an interface, and then provide a custom implementation just for my unit tests. Instead of having my class construct a database connection directly, I'll make it passed in as a parameter. Then they'll be nice and fast!

3. Whoa, now my tests run instantly! How great. This mocking pattern is awesome. I want to mock everything! But hmm, I have a lot of objects and they often depend on other objects, like services of some sort. And I was told in school that God Objects and global variables are bad. So I can't use those because I want to be a good programmer and good programmers don't use those. This is making my code kind of a mess because now every time I want to construct an object it takes lots of parameters when before it didn't.

4. <reads some article on hacker news> Hm, this dependency injection library sounds like what I want. Instead of constructing my objects directly, I ask an "injector" to do it for me. And it will then consult a table of bindings, and then find or construct the dependencies, and then build the object I want, recursively. All I have to do is [insert long complicated process here].

5. Meanwhile, some other programmers look at what's going on. Interesting! They say. Those programmers know what they're doing and they're converting their whole codebase to use dependency injection. They claim it's a best practice to make testable code. We want our code to be testable too, we should do the same thing. Plus, we can call this refactoring and code maintenance and get paid for doing essentially brainless work, instead of having to take risks on developing new features or fixing bugs.

The story ends like this: pretty quickly this newfound "best practice" is spreading throughout your codebase like a fire, and now when you deploy your app, you get an error whilst the app is running. You then try to figure out what's causing the error but 25% of the time you try to follow a method call you end up looking at an interface instead of code, and when you try to figure out what implementation of that interface your app called you have to read and decipher tons of binding definitions.

The correct place to stop in the above story was at point two. And the reason is not just code readability. Once you start over-using mock objects, you can start to discover that your mock is implementing what you think that service does, not what it actually does, and you can end up with code that's actually buggier than code written with traditional fat test dependencies would have been. Fail.

Thank you, very detailed explanation.

I will point out that the run time problems of guice are trying to be solved with dagger: http://google.github.io/dagger/

I agree with your take on this. Part of language arguments roots in the "assumptions of the Blub Paradox": that there exists some strict ordering among languages (and therefore some language "blub" that is superior to some and inferior to others).

I find this hypothesis questionable. It's likely that language "power" in the real world looks more like a loosely-ordered graph, with plenty of bidirectionals tagged with things like "If you are doing lots of matrix algebra" or "If you need the thing to run on a Raspberry Pi." Go solves a specific domain I operate in (data structure transformation and web services) really quite well---well enough that I can move from making the problem fit the language to solving the problem with small amounts of work, without worrying that I'll create a testing nightmare for myself in the future.

When I find a task too big for Go, I'll amend my feelings on the issue.

Huh, funny enough - Go was my first try to replace PHP, but as I don't share opinion "copy-paste is better than generics" and "executable comments are ok", I tried Rust, and now I have REST API with 10000+ LOC - it serves multiple web apps and works just awesome and I really feel fun of programming and I'm enjoying language. So "I don't know why you'd want to write a web app in Rust" sounds ridiculous for me. Really, "I don't know why you'd want to write a web app in Go".

"executable comments are ok"? Where did you hear that?

Go has many "special comments" that actually do stuff:

* build tags (https://golang.org/pkg/go/build/)

* code generation (https://blog.golang.org/generate)

This is the exact point where you start to see that the Go creators are ok with hackery as long as it works and doesn't make the overall design too complicated.

It looks like we agree Go has "special comments", not "executable comments".

I recognise that Go' special comments can be seen as a hack, but honestly they are not so different from Rust's attributes or Haskell's pragmas, which can look clunky too.

No way. Comments are comments, attributes are attributes. Previous discussion: https://news.ycombinator.com/item?id=9522973


When my primary platform moved from C#/ASP.NET to Objective-C, it took me a while to realise that one of my biggest reliefs was that I didn't have to deal with "software architects", and just to get on with coding. I began to realise that so much of that coding came down to "justify my existence" (as architect) -- needless complexity to check off a box from the gang of 4.

Mind you, having an architecture in mind is of primary importance, but dealing with such complexity and endless Factories made it impossible to follow the code.

And yes, I know that server-side implementations have an inherent complexity that most client-side apps lack.

I'm not sure that using C# inherently turns you into an architect. You can write the most direct and legible code in C#, just as you would in other languages. I think it is a mistake to conflate the two. In fact, I've seen it.

I am sure that as you work your way up the Objective-C chain, you will run into patterns and practices that have brought the best results over the years. They will feel burdensome after a while. At that point, you will be right back where you were with C#, except in Objective-C and will be happy to be a beginner at another language so that you are free of the burden of experience.

Agreed, that C# doesn't inherently turn you into an architect. It's more like C#/Java has a culture of 'architect'.

Objective-C is seriously in MVC-Land (or maybe MVVM-land too), and pretty much discourages the more convoluted design patterns that I saw back in my server dev days.

Indeed Go is a pretty good "Google Language". It almost google's C++ with it's C style guide baked into the language. For almost every feature in Go (or lack of thereof), I can find a line in the C style guide saying the very same thing. (ban of exceptions, rvalue references, don't include what you don't use, CHECK vs. panick... etc)

(Though yet many teams didn't adopt Go. Because if none of your teammembers has Go readability then you have to rely on someone in Go team to do CRs. Those guys are not very pleasant to deal with.)

"Those guys are not very pleasant to deal with."

I got Go readability more than 2 years ago, right before I left Google, but in my experience the Go team was very pleasant & professional. Has that changed?

FWIW, I have relaxed my opinion on web apps a bit ;) I do think that it's not a strong point, but there are places swhere it could make sense. Especially with some more libraries. I thought I made a comment more recently than https://news.ycombinator.com/item?id=10312354 , but whatever. :)

But the general point does stand: languages have different strengths, and that's totally okay.

> "wow I read this code and I can understand what's happening and hack on it to do something else."

I think that's the issue. For many things, that is perfectly fine. But for other stuff (finance, healthcare, safety critical, anything that loses real money/lives when it breaks), the last thing I want is somebody to just "hack on to it".

by "hack on it" he/she means being able to 1) easily understand it by looking at it, 2) easily figure out how to modify it (to add functionality or change it). You are reading "hack" as a bad thing when really it's a good thing.

Anything that evolves over time requires changes. All of the examples you give (finance, healthcare, safety, money/lives matter) are better served with people being able to read and maintain that code.

That's a relative term. Go will give you static type safety (until and unless you [inevitably ;)] break out into the 'reflect' package) and strong assumptions about what default values mean in data structures. These are very nice features to have in terms of trading off flexibility for expressiveness.

Python is not a language I would trust in healthcare, finance, etc. on the critical path of consuming and transforming user-supplied data. Go I'd be comfortable with.

  >  It's often been said that Go solves the problems Google developers have, and
  >  it's 110% true. 
I'm wondering how much of what you're experiencing is "Good Go" vs "Bad Java"? I feel like you can take any project in any language and screw it up pretty badly. I'm an iOS developer and I've seen developers bring questionable practices that aren't consistent with the Objective-C ecosystem in and cause all sorts of confusion. I'm sure there are a few other languages that would give you the same positive experience if you tried them out.

It's possible that Go hasn't been around long enough for anyone to screw it up badly. But that'd be a strength in the ecosystem of languages.

Many of the comments here evoke that feeling : that Go doesn't have compromises.

History teaches us that this is not in fact the case. Reality is that Go doesn't have too many compromises ... yet. I've run into more than a few already, and the cracks are visible, even if they're not yet too deep or expanding. (e.g. the logging struct, which prevents you from overriding logging destinations or adding logging contexts)

Every language gets a honeymoon phase. Once you program for a decade or so, you'll start remembering those. Java, for instance, had a great, and very long honeymoon phase when the concept of garbage collection and VM based languages was new, at least in mainstream languages. The cracks and compromises are what killed Java, and these days the cracks are regularly in the way, or at least visible.

Google has to statically link everything to produce a big binary with almost no dependency (besides syscalls), because it cannot promise the environment of the server, as you might get different boxes between deployments. So, it links all the jars and jvm into a huge binary, it's a pain to deal with that because it takes minutes to build and see your change.

And still, Java is almost used for front end only. When memory is not enough, you have to use C++.

Totally agree with your comment about monolithic code. I'm in a similar situation, at work I am primarily in a PHP pile of spaghetti, but in the past 2 months I've been lucky enough to develop micro services in Go.

Once I got over the initial learning curve and started to get the nuances I really enjoy working in the language. So much so I've started looking around for a full time Go position.

I have the feeling that golang is very focused on pulling code from github, but I've had a hard time packaging golang applications. I have succeeded with go-ipfs, which vendors all dependencies and includes them in their release tarballs, but I'm not sure how to do that with other applications which import dependencies from github.

I think there is a better explanation for why people dislike Go. All programming languages currently used for the web have gigantic downsides. They're slow. They have terrible package management. They have poor standard libraries. They have no static typing. They have no visual debuggers. They have no good IDE support. They don't integrate well with frontend code. Some programming languages are more flawed than others, and no programming language fails on every front, but they're all pretty objectively terrible.

Then Google announces Go. A cross-platform systems programming languages for high quality web services. That sounds great! I can't wait to see what Google came up with.

So when people saw Go disappointment set in. It has some great properties, but the language is not expressive. So Go web frameworks (like Revel) generate Go code at compile time to get the dynamic parts working. Just like we did in the 70s to work around C's shortcomings. Want a container for a specific type? Code generation! It's so clumsy. The lack of exceptions makes writing correct code really tedious. A web service is not a device driver where every edge case has to be carefully considered. Bailing out with an exception is fine. Go disagrees.

I think the disappointment in what Go could have been explains the vocal dislike. There are only a few companies in the world that can create a new programming language and ensure it becomes popular. Don't get me wrong. Go isn't a bad language. It's just not the language that will push the web forward, and Google was in a unique position to create a programming language that would.

"All" languages used for the web have those downsides?

This is part of why Go culture scares me a bit. You seem to be overlooking the huge amounts of software written in .NET and on the JVM, none of which suffers from the problems you just outlined: there are great IDEs, decent type systems, good interactive debuggers, strong standard libraries, reasonable package management etc.

This mental blind spot towards the tools and practices that a massive part of the software industry has been using for years is really odd.

I deliberately didn't mention specific programming languages because I knew that would lead to bickering about the relative merits of Python vs Java vs .NET vs Clojure, which would just distract from the greater point. Your curious assertion that I'm somehow part of "Go culture" only confirms this.

I think we can do a lot better than .NET or Java. .NET isn't even cross platform and Java has a lot of legacy cruft. Not to mention both platforms are pretty bloated and not even designed with the modern web in mind.

So much bias in this thread in general. Have you missed the news on .Net Core?

A sample from the newer stuff in the .NET world: http://nancyfx.org

How modern is that for you?

Same old same old? If you think nancyfx represents a leap forward I don't know what to say.

It's not clear what you would accept as a good language for the web. Could you elaborate?

Comparing to the old ASP.NET web sites with "view states" and "user controls"?

Sounds like leaving behind the "legacy cruft" you talk about to me.

Java and C# have a first class ideology (object oriented) that does not align well with functional web servers which is how almost everyone writes theirs nowadays.

These languages are getting better about it, but they are tacking on functional programming to a language that traditionally was strictly OO, and in the same way C++ has a lot of edge case behavior in being "OO tacked onto imperative" these languages suffer similarly.

Both of those languages have migrated to more functional features with closures and lambdas. In fact, it seems like the entire landscape has tilted a bit toward the functional side in the last ~5 years.

Last time I checked there was plenty of FP choice on JVM and .NET stacks.

That's not a true statement about modern C# and Java.

"Decent" is being very kind to any language that has a type system where every reference type is implicitly a Maybe (okay, Scala exists).

Go and Scala also allow every pointer to be null, no? Scala has an option type, but so does Java 8. Defining one in C# is easy.

But there is Ceylon, Kotlin, Clojure, whatever. Kotlin uses ? suffixes to define if something is optional. And at least the code interops nicely. You can inherit a huge Java codebase and slowly convert the code over. No such luck with Go. Unless you're converting into C!

C# and Java optionals aren't very useful, since they would be reference types themselves, and thus could be null!

I would submit Rust and Swift as "decent" type systems, if Haskell is the standard for "good". They do nullability correctly, but lack HKTs.

C# has non-nullable value types via the `struct` keyword. And C# in fact already has a defined optional type to handle this; it's called `Nullable`. [0]

[0] https://msdn.microsoft.com/en-us/library/b3h38hb0%28v=vs.110...

In Scala, Option[Whatever] may also be null. The difference is that it's considered "some Java compatibility leftover" and never exploited by any sane piece of code.

> A web service is not a device driver where every edge case has to be carefully considered.

Yikes, that's an assumption that is going to bite you hard in your career. I recommend escaping it as soon as possible. ;) The web is full of horror stories from people who assumed their part of a web-accessible product wasn't on a critical security / safety / reliability path.

I used to use Python and Ruby on Rails for web services; this is precisely why I left them. I got tired of dealing with typos becoming runtime exceptions.

> Bailing out with an exception is fine. Go disagrees.

Go makes it trivial to bail out with an exception: You panic. But panic is reserved for real exceptions, not common and expectable situations (like "file not found") and its defaults are therefore set to crash the whole process (which is fine if you're doing microservices and therefore can handle failures by crashing and restarting). I find other languages treat exceptions as not sufficiently exceptional.

> I used to use Python and Ruby on Rails for web services; this is precisely why I left them. I got tired of dealing with typos becoming runtime exceptions.

That is why you must do 100% code coverage on all non-compiled language.

"The lack of exceptions makes writing correct code really tedious."

Tedious up front often translates into time saved down the road. Exceptions are often an easy way out while accruing future debt.

Unfortunately, our industry cannot easily measure the time saved down the road and so cannot properly value it. However, many with long term interests in a project will often spend on the "tedious" costs up front to avoid potential future costs.

Lack of non-local dynamic control transfers with unwinding is the real deal breaker.

Exceptions are a red herring; they are just something you can build if you have dynamic control transfers with unwinding. And if you have macros, or at least some kind of access to the language to bend the syntax. Plus perhaps other goodies like testing whether some object X is of a type which is a subtype of T so you can make exception handling frames decide whether the elevator stops here.

The underlying control mechanism not being there makes the language crippled.

Just give me C. Then I also have forty years of research out the window: but but at least with setjmp and longjmp.

How does Bash recover to the top level prompt when the scriptage fails deeply nested in some function calls? Why, longjmp! I will fake the unwinding if I have to.

Go has panic()/recover(), which is better than setjmp/longjmp (thanks to GC you won't leak memory like you would in C with setjmp/longjmp).

I'm not saying using panic()/recover() is a good idea but if your issue with Go is lack of non-local dynamic control transfer then good news: you're mis-informed and Go will be great for you!

It's not just up front. You only have to write the tedious and repetitive code once, but you have to keep reading it forever, because the code you care about is scattered here and there in the middle of it.

> Exceptions are often an easy way out while accruing future debt.

Is there perhaps a concrete illustration on how using exceptions causes technical debt, especially in a GCed language like Go?

The advantage with go is that errors have to be handled right away by the thing that may have caused it. The is versus, say a try/except with a dozen lines of code in the try, and then something like `except KeyError: pass`. You may have no idea which line caused the error or why it did so.

The general principles for fault tolerance require Separation of Concerns vis. Error Encapsulation (make sure that the contagion doesn't spread), Fault Detection (make sure that you know that someone is infected), and Fault Identification (you have ebola!).

Error encapsulation (and this applies equally to modules, components, systems, architectures, organizations) is invariably best done at the lowest level possible, which invariably breaks #3 and #4 (fault detection and identification).

what if you have different classes of exception handling mechanisms available for each of these cases? What about languages that may support exceptions, option types, tagged values, multiple return values, signals, continuations and/or whatever mix of them that exists?

The problem with handling everything right away is that it lacks flexibility to handle things in what could be the optimal manner. "One true form of exception handling", to me, sounds as reductionist of an approach as "one true form of concurrency", "one true programming language paradigm", or whatever.

Treating all error conditions / exceptions with the same mechanism will generally ensure that you pick similar stances on encapsulation vs. detection and identification for all error conditions / exceptions, unless you decide to be extra careful about all of that.

Using multiple mechanisms will allow you to pick, case by case, which one you feel is worth breaking depending on the nature of the fault and what your specific application or system requires.

I feel Go is doing a pretty bad job at this.

Actually the real idiom is not "handle errors where they happen" but rather "errors are values" (https://go-proverbs.github.io/). This means that there is no one true way to handle errors, but rather that it's up to you to build error management with the same tools you have to manage data. Maybe you want to process a list of stuff in parallel and report the first error that ever happens, the same way you'd want to use the first useful data that was processed by one of those parallel processes. Maybe you want to multiplex the error to multiple error processors, for some reason. Maybe you want to signal a watchdog but continue working. I believe bubbling up the error is a consequence of the Go community still being young and not having invested a lot in proper error management (especially since you don't always need something fancy) more than it is an idiomatic way of working.

That's the thing though. Errors can be data in plenty of other languages. It's just that it's not the only tool you're given, and there's other things you can do without having to reimplement it all from scratch every time.

Where a lot of people will say "go is opinionated", I keep feeling that Go is just not providing facilities I feel are part of what you should get out of the box (much like a standard library is one) and just shifts the burden to me to reimplement them all correctly. In doing so, you also lose the opportunity to have a well-designed approach that gets rather uniform adoption through the community.

I know the feeling. Having moved to Go from the Python community I felt extremely scorned by the lack of a lot of features. Why should I have to write a for loop to traverse this list just to see if an element is present? What I've found is that the features that are missing are actually extremely simple to implement myself - to the point where it's comical that I ever complained about them. The things you gain, however, are much more powerful. There is an elegance to go code that can't be matched by dynamic languages. It has the readability of Python with the type safety of Java, and tooling built in that simply trumps both. I'm obviously a big fan, but it was a long and difficult journey to get there.

"The problem with handling everything right away is that it lacks flexibility to handle things in what could be the optimal manner."

You can pass the error (or another) up the stack. The language is flexible.

> You can pass the error (or another) up the stack.

(C++-like) exceptions pass the error up the stack. Directly to the right place, and ensuring that clean-up takes place along the way without tons of repeated test-and-bail code.

Lisp-like are one better: the stack is searched for a binding to a function which handles the error, and then a new call is generated to that function. If the function returns, the search for the next possible one continues. Or the function can then look for a restart point somewhere the stack (the entire stack still being intact), and perform a dynamic non-local transfer (a big return) to that point.

Dumb error return values make it very easy for an error to disappear without being handled. Oh, the caller has a few things to do before returning your value (things such as clean up that could be an unwind block!) and fumbles the ball somehow, and ends up returning a different value: the information is altered like in the telephone game.

That's the problem: every function level between the source of the situation and the place where it is to be handled intercepts the handling effort by being involved in the control flow. When it should just be getting the heck out of the way (like cars pulling to the side when they hear an ambulance).

Bubbling up error values is an excellent example of an "Anti Pattern".

Not handling an error from something you called into will lead you to be bypassed when it jumps "directly to the right place".

"Passing up the stack" is fairly minimalistic in an environment where you could be running thousands of goroutines, some (many?) of which may share memory.

If you do it that way, you seem to forego a lot of error encapsulation straight away and quickly find yourself into undefined territory.

doesn't matter whether no goroutines or thousands - you either handle errors or pass upwards. Anyhoo, just pointing out that it has the flexibility to do either.

mononcqc is pointing out that those aren't the only options: other error-handling mechanisms exist. The options are not either "handle the error right now" or "make the caller handle the error".

In fact, in go those aren't even the only options, since you can pass an error object up the stack using panic/recover.

An alternative model could have error handlers registered somewhere and be invoked at the point the error occurs, either choosing to pass control to another part of the program, or resolve the issue and continue processing. That could, of course, be implemented in vanilla Go, but then everything has to agree to do that.

Some systems are able to distinguish the point where you recover from an error from the point where you report an error: e.g. a batch processing system may recover from an error by skipping an item to be processed (and perhaps storing it in a list of failed items to be inspected later) and another "catch" handler further up may decide whether and how to display a diagnostic about the issue. Of course, this logic could be embodied as a "reporting" object which is passed down to the batch processing algorithm, but hooking into the exception handling logic means that you can use the existing error-reporting infrastructure.

Common Lisp has a system of "restarts" where one can configure multiple ways for a handler to respond to errors other than simply passing it up or carrying on. For example, a batch processing system might set up restarts to allow items to be skipped, retried now, or retried after the batch finishes. The batch processor itself might have restarts for retrying the batch or rescheduling it on another node. Above the batch processing algorithm, an exception handler can look at the situation from a high level and decide what to do: e.g. it may determine that the batch has grown too big for the node and reschedule it on another one.

Until the decision is made, the stack is not unwound, so if I decide to restart an item from the batch, I just jump right back into the still-running batch processing function. This design allows the mechanism for how to actually deal with an error condition to be separated from the decision as to which mechanism to use. It's very much like breaking into a debugger, except the program can debug itself.

In Erlang, a program handles errors by keeling over, dead. Because an Erlang system is (meant to be) designed as a swarm of cooperating processes, an individual process can just die when something goes badly wrong and its compadres are expected to have registered an interest in knowing that this has happened. A common design pattern is to have a dedicated monitoring handling process which knows how to orchestrate things so that one broken process doesn't cause a cascading failure through the whole system.

In the running example, a batch processing system might spawn a process for each batch, and a monitor process might check for batches which die and then decide whether and where to restart them.

That said, Erlang still has a fairly traditional try/catch system for when that makes more sense. And errors are objects, so you can return them up the call stack as well.

There are many more mechanisms for error handling which aren't simply "handle here or pass up".

Conversely, the disadvantage with go is that errors have to be handled right away by the thing that may have caused it.

Sure, with a `try`, you may have no idea which line caused the error or why it did so, but that isn't what matters. After all, if a function returns an error, you don't know what line of code actually caused the error. (Especially in go, since errors lack backtraces.)

With "exceptions" you know that something within the block failed and passed the information about what went wrong to the catch/except/rescue block. Problems arise if the block fails to tie up its own lose ends, but that's a problem that exists without structured exceptions: if a function might return an error you still have to take it on faith that it arranged for clean-up of any state that, outside the function, would be problematic.


    try {
    } catch e Fred {
    } catch e Barney {
isn't really any different from

    if e := (func()error{
        if e := foo(); e != nil {
            return e
        if e := bar(); e != nil {
            return e
        return nil
    })(); e != nil {
        if _, ok := e.(Fred); ok {
        } else if _, ok := e.(Barney); ok {
        } else {
            return e // assuming this function returns error
except that one of them is far more readable.

It's potentially different, of course, inside foo(), where it might unexpectedly call a function which raises. But because recover exists in the language, robust functions must assume that any function call, or various built-in operations[1], might result in code further up the call stack recovering from a panic, so it must make sure it will fix its inconsistent state when the stack is unwound.

Additionally, go is inconsistent in that some errors - e.g. array index out-of-bounds - cause panics instead of indicating errors normally. That's understandable, since having to type

    if c, ok := array[i]; ok {
      err = fmt.Errorf("Array index out of bounds")
    } else {
      // do something with c
every time you wanted to do

    c := array[i]
would be really tiresome.

[1] Such as: comparing non-comparable objects via references of interface type; dereferencing a null pointer or interface; out-of-bounds array/slice/string indexing; division by zero; sending on a closed channel. All likely occurrences.

GC means that most memory leaks cause by poor exception handling code are auto-magically fixed but it doesn't fix other resource leak problems; file handles, memory maps, locks, etc.

Nope. Because like most popular language constructs they can be used effectively or poorly. There are a ton of completely valid arguments on both sides.

Elixir is fast, has good package management, has a good standard library, exceptions are easy to read and debug, etc. Elixir doesn't have static typing, but it is functional, so it doesn't really matter as long as your initial assignment is correct. I can't really comment on IDE integration, since I never use anything but Vim.

Maybe the static typing and IDE support are enough to make Go awesome for some, but they don't really matter to me as much as concurrency, hot-plug code deployments, the actor model, and stability.

Elixir has optional typespecs that can be statically analyzed with a tool called dialyzer: http://learnyousomeerlang.com/dialyzer

I can really relate to your post. I heard about go at a time when i was angry against python for having no type hinting and started to see people build tools parsing types in code comments, and at the same time being furious against the gigantic bloat that the java enterprise web frameworks had become.

So, as you said, when i looked at go being a smart and small with a modern standard lib, and being modern in a way with its approach to interface programming i thought i would fall in love with it.

Then i saw go didn't have a single generic function for comparing two numbers, because the language wasn't generic enough, and i felt hugely disappointed.

If you avoid Spring, you can find some pretty nice and straightforward web frameworks in the Java space. The reason they often seem bloated is simply because they've been around a long time and so have accumulated many features.

If you want something similar to the Go standard library HTTP server, there is this one that comes with the JDK out of the box. Most people don't know it's there though, as technically it's not a part of the Java platform, it's just something that comes bundled with the standard JDK:


If you're building a serious app you will want support for more advanced stuff. That's when you can upgrade either to a better HTTP server like Jetty, or to a full web framework that bundles templating, authentication, database access, session management and all the rest. Play! Framework is quite well known. It ignores all the standard enterprise Java conventions in order to be a lot more opinionated. If you like their opinions, that sort of approach can be way lighter.

Why would you even want that? I mean, I've heard the generics argument before, and I'll accept that they are important for some applications (esp custom data structures). But lack of a generic `Cmp` is the straw that broke the camel's back?

> Then Google announces Go. A cross-platform systems programming languages for high quality web services.

Did they actually advertise it as a language for web services? I thought it was designed for command line tools mostly, not for serving HTTP/HTML.

The first version of the Golang web site doesn't mention the web: "A systems programming language: expressive, concurrent, garbage-collected." However one of the first programming examples on the Effective Go page is a web server.


Looks like you're right. This is the original announcement: http://google-opensource.blogspot.com/2009/11/hey-ho-lets-go...

I came here to say this. It's not fair to criticize Go as not optimal for web services if it wasn't designed to be optimal for web services.

> A web service is not a device driver where every edge case has to be carefully considered. Bailing out with an exception is fine. Go disagrees.

If all you want is a bail out mechanism then panic.

> The lack of exceptions makes writing correct code really tedious

Go does have exceptions.

A web service has to consider errors more carefully than you might think.

People who dislike X are upset because they incorporated their favourite Y into their identity, and the success of X challenges their own choices.

True for football teams, political parties, games consoles, superhero franchises, religions, food choices, colour schemes, preferred spelling variants, ...

Sometimes, sure. But none of those are our jobs (except if you are a football player, politician, etc).

Computer programming languages are our jobs. It's okay to have preferences. I (a full time front-end webdev), think Python is probably the best language out there. But it doesn't define me, because that's just silly.

I should probably have added "job" to that list. People certainly define themselves by their jobs. Not everyone all the time, but you can see it cropping up somewhere all the time even within a company.

And job grades, job titles, job seniority, place of education, type of degree, ...

I agree that a language doesn't define you but what I wonder if a person's favorite language has some correlation to certain personality traits. I would be lieing if I didn't say I get more enjoyment from some languages where other people don't. Perl vs Python for example, pythons core values are to try and make it only one way to achieve something, whereas Perl tries to give you multiple ways to achieve something. I would guess that Perl may appeal more to artistic people and Python would appeal to more engineering type of people. This isn't a claim, more just something I think would be interesting to investigate.

Ok, I write every day in Rust and JavaScript (and not just jumping monkey in JS, but a lot of code). They are almost orthogonal languages. Will it fit your theory? :)

Are they both your favorite languages? Also there will always be exceptions.

Sorry for long reply. No, I prefer Rust, but right now it's impossible to use Rust on frontend. I also know there are people who love Python, Scala, Nim, D, Ocaml and I don't think they are wrong - it's just languages with different flavours and there are people with other preferences, so it's awesome to have alternatives. They are not better or worse than me if they use other languages, I'm more than sure about it. But when we talk about PHP, Go, Perl - yes, I think people could make better choice.

That's actually an interesting philosophical question. I find the idea of "more than one way" extremely unappealing, so it's not particularly shocking that Python is my "ideal" language. To me it's either useless (all options have the same efficiency) or it's bad (one option is the most efficient). So it seems senseless.

And artistic is the last word I'd use to describe myself.

Poor post. One of the worst thing you can do in a debate is to psychoanalyze your opponents, ascribe their stances to some sort of personality trait, and ignore the object level. More mundanely, it's just ad hominem, "haters gonna hate".

What little object-level substance is to this post is laughable. Basically: since Go doesn't have modern language features but it's evidently popular and works, all the people who like modern features are upset since it turns out the modern features aren't needed, after all. Half irrelevant, half assertion out of blue air.

It's so easy to dismiss legitimate criticism of any issue as "hate" and "people are emotional" and "their identity is threatened".

At the end of the day, there is legitimate criticism of Go, just as there are legitimate advantages of using Go. As an additional fact, Go's core developers (and some users) have repetedly been dismissive of this criticism.

Yes, this article tries to make it sound like issues with Go are solely due to identity, but that's not the case.

If I like to use soap and analgesics, is that part of my identity or just common sense application of technology?

There are studies that suggest using analgesics may negatively affect your judgement, so there's that.

I haven't used go so far and much of its criticism might be overblown - but to be honest, that article made me immediately dislike the author.

The basic argument of the article is that "People who dislike Go are upset because they incorporated their favourite programming language into their identity, and the success of Go challenges their own choices".

That can be summed up as "People who dislike Go do so because they have been hurt psychologically".

Apart from being disrespectful to the community of other languages, this basically makes it impossible to give a counter-argument: Whatever kind of argument you bring, in the end you would simply add support to the author's theory because, in fact, you have been trying to criticise the language, so you must be hurt. I don't see how that contributes to a fruitful discussion.

I've been working in Go now for over a year and its honestly made my day-to-day life as a software engineer enjoyable. What gets me down about working in this industry is toiling away on products only to never see them released or being frustrated by absurd compile times, poorly tested components and abstract cathedral architectures. I worked on large C++ projects for around 7 years and i don't care for another flame war about curly brackets or which reimagining of a string is more ascetic. I also worked in Ocaml and some Erlang and yeah while great in principle they lacked the out-the-box tooling and standardisation of practice that I absolutely love about Go.

If someone creates a ML variant with a day-to-day experience as clarified as Go then I will gladly jump on board.

> "If someone creates a ML variant with a day-to-day experience as clarified as Go then I will gladly jump on board."

What about F#?


As a side benefit, it's appears to be the top paying tech worldwide ...


... as well as one of the most highly regarded languages by those who use it ...


Even if you end up not liking it, I'd say it's worth a try.

I hadn't really given F# serious consideration, i know it's based off of OCaml but looking at it now i'm not particularly enamoured by the idea of managing threads, or doing async programming. Yes it does have an actor model but it looks limited to just a message box.

I think Microsoft Orleans is the most interesting functional language based on .Net http://christophermeiklejohn.com/papers/2015/05/03/orleans.h...

> If someone creates a ML variant with a day-to-day experience as clarified as Go then I will gladly jump on board.

I think Kotlin and (eventually) Swift comes very close, but both have compatibility as a high priority, which complicates the languages a bit. But I'm hoping these languages will be able to serve as gateway drugs into the world of ML-style programming, and that we'll soon see a no-compromise ML-style focusing on the full experience.

I tried swift a while ago, but the bugs turned me away from it. that and having to use xcode. I'll have a look into Kotlin, thanks!

Article didn't convince me to think following arguments are wrong:

* Go is a language stuck in the 70’s.

* Go ignores 40 years of programming language research.

I tried to use Go and was shocked how they can use it without package manager, without generics, with so brittle concept of channels, with executable comments in code and with so authoritative model of taking decisions about language evolution.

So I still think criticism of Go is valid and authors are still deaf to it.

I feel like the designers of Go tried to address criticism of C without considering any language designed after C. As a result there are improvements to some of the most egregious shortcomings of C (undefined behavior, a lack of basic reusable building-block data structures like lists and maps, crude build systems), but the subtler issues with C are still there. You still need to delicately route together error signals from every procedure which could fail. You still have a very limited ability to create new, reusable data structures. Common patterns are copied and pasted around your codebase because you have limited tools for abstraction and reuse.

Go proponents claim it's simple. I'm more inclined to call it simplistic.

What are executable comments?

``Go is not meant to innovate programming theory. It’s meant to innovate programming practice." – Samuel Tesla


And as usual, http://9front.org/who/uriel/

And as usual, http://9front.org/who/uriel/

Can you give some background?

I've never known anyone who's favorite movie was Three colors: blue. Maybe I've found my spiritual doppelganger.

Go itself is a cool tool. Crosscompiling stuff, a great standard library, nice toolkits like gorilla and marshalling from/to structs/json/xml comes in handy for small everyday tasks and the primitive imperative style combined with easy-to-use goroutines and quite good performance ... together its a very great tool.

But I just can't stand the "the go way!" people who defend every fault the language itself has with this mantra. I use go sparingly for small scripts and little services, but would never ever use it for big projects. Yes, for programming rookies in a team its very easy to get started to make valuable contributions, but I for myself just want a more adult language with rich expressiveness and actual static typing (interface{} vs. generics sigh). I understand Go as a "compiled PHP" with all the pros/cons one would associate, and accept that it aims to be a "C as it should be".

I do not hate Go in any way, I use it when appropriate.

(PS: I recently realized for myself that Rust will be the ultimate game changer, just give it a few months/years to grow mindshare organically. It's everything but a beginner language, though.)

What is an "adult language"?

> Go is the only recent language that takes the aforementioned 40 years of programming language research and tosses it out the window [ ... ] no pattern matching, there’s no borrowing, there’s no pure functional programming, there’s no immutable variables, there’s no option types, there’s no exceptions, there’s no classes, there’s no generics.

Some of this stuff is quite a bit older than 40 years. That only brings us back to 1976. Exceptions are around mid 1960's or so (PL/I, Lisp). Functional programming, Lisp again, 1958. (Java-like) OOP Classes? At least as far back as Simula-67. Simula-67 is where C++ gets "virtual" from.

It is a bit more nuanced. Go's dislike is a function of how vigorous the hype for it was vs. how much it actually delivers + a few other things. In general I see it as this function:

  def dislike(hype, results, community, usage): ...
Note the usage, if technology is not used, it won't be disliked. So dislike is a good sign sometimes. Community attitude matters, how are creators and developers treating others, how are well are docs presented, but also how mature and behaved are the advocates of the technology. That is something creators can't necessarily control.

Other hyped technology is/was node.js. I've heard people say crazy things about, it is the best technology, everyone should drop everything and join the winning team etc etc, async programming is the future and if you are still using threads you are stuck in the past and so on. So it was hyped quite a bit. And then it would have been ok, if it actually delivered, if packages weren't broken and half-assed, if servers under load actually didn't crash and so on. If people who used it where a bit more mature, if there wasn't drama at every step and so on. So it ended up disliked quite a bit.

PostgreSQL is hyped, people are saying this is the end and all database and so on. But it is not disliked, and the reason is it actually delivers results. It handles JSON blobs, it does other things right, it doesn't catch on fire, doesn't throw your data to /dev/null. So it not disliked.

As for Go, I haven't used Go, so I don't have much of a comment, but noticed an interesting nuance with how some technologies just happen to be disliked while others, even if hyped are ok.

I'm one of these ML-derived ideologues this article disparages. I hate Go precisely because of the reasons outlined in this article. In my perspective, OCaml and occupies mainly the same niche that Go does (same balance between high-level and low-level, same skepticism of the object oriented orthodoxy, etc). OCaml is a much better language than Go for so many reasons that I will not go into here.

I'm also a Googler. Rather than inventing Go, if Google instead would have made OCaml its "Go", the world would be a better place than it is today. If the same tooling were built around OCaml, with some problems of its implementation fixed (multicore/parallelism, etc), there would be no complaints.

Couldn't this argument be made about all languages? People into dynamically typed languages would have statically typed languages for the same "don't touch my identity!" reason.

I personally don't "hate" go. To be honest, I have barely read 20 lines of go ever. But I do not like the idea of a language specifically designed to limit my possibilities. I want to keep seeing "programming" as an art and a creative activity. Not as a factory-like process where there is only one way to do thing, all developers are inter-changeable, etc.

I get why it's interesting for big corpos like Google. I just don't have to like it :)

Nature works in the same way that it limits us to the fact that an effect can only be obtained by its commensurate cause. Anything is possible through that law as long as the appropriate cause can be formed.


In math, answers are made by questions. In life, the quality of your answers is determined by the quality of your questions. So make a concrete question based in reality if you want a specific, real answer that you can confirm against proof.

Wow, you did all that nature analogy to say that the misunderstanding lies in the question and not in the answers?

That's incorrect. I was talking about your useless "What??"

Seems most people don't understand that Golang is filling a niche that was not covered by anyone: fast, type safe, portable, memory-managed, simple.

Every language sucks at something. Switching from Ruby/Python to Golang feels like losing magic powers, yes, but some problems are better tackled without that magic and type safety comes as a plus.

Ruby/Python/C/Java/Scala/Erlang/Elixir/JS/Haskell/Lisp/Clojure/Rust all have different niches. We should really get over it.

> Go is the only recent language that takes the aforementioned 40 years of programming language research and tosses it out the window.

> The mere existence of Go says “your views on what makes a good programming language are wrong”.

As someone that dislikes Go, that's not it. It's because Go doesn't "own" the fact that it thrown language research out the window.

If Go advocates waved their imperative programming flag proudly I would just ignore the language completely.

I don't hate Go. I think the language is half what it could have been if designed more carefully. I don't doubt Go designers skills, I just think they just stopped half way for various reasons. Which makes Go a bit frustrating.

However, I hate the Go community, which doesn't hesitate to humiliate people trying to use language in unconventional ways (Martini...) and mock people that come with a valid criticism of the language (rigid type system, lack of dynamic linking, package management...).

So good language despite its flaws, horrible community. Now is it useful? It'd be like asking if Python is useful despite its flaws, yet Python has a great community unlike Go.

> humiliate people trying to use language in unconventional ways (Martini...)

The author of Martini, Jeremy Saenz, didn't feel humiliated:


> lack of dynamic linking

You can build and link shared libraries since Go 1.5:


> package management

The Go team is listening to the community about package management and is even willing to make changes:


I agree that Go is a conservative engineering project, which can explain some answers you read on Go mailing lists, but I think you mischaracterize the community.

I would add that I'm tired of people repeating that the Go core team is stubborn and doesn't listen to critics about the lack of generics, even though they have provided substantiated answer on this topic:


I'm wondering who is not listening to who?

> You can build and link shared libraries since Go 1.5:

That was not my point and you know it. you can't load shared library at runtime with Go. Like you can do in most languages out there.

> The author of Martini, Jeremy Saenz, didn't feel humiliated:

Yeah, he didn't feel humiliated so much he stopped writing about and programming in Go and interacting with the Go community all together because it's full of bullies.

> The Go team is listening to the community about package management and is even willing to make changes:

The Go team is listening to nothing.

> I would add that I'm tired of people repeating that the Go core team is stubborn and doesn't listen to critics about the lack of generics, even though they have provided substantiated answer on this topic:

That doesn't make them more open to changes, anybody can do an AMA for PR.

Go community is blind to its own shortcomings and the language issues, you just proved my point yet again.

> you can't load shared library at runtime with Go.

I've read again the documentation, and you're right: it's not possible as of Go 1.6.

> Yeah, [Jeremy Saenz] didn't feel humiliated so much he stopped writing about and programming in Go and interacting with the Go community all together

It's true that I don't see Jeremy posting stuff on its blog, Twitter, GitHub or elsewhere since a few months, about Go, or about anything else. But how can you assert it's related to the Go community being harsh?

> That doesn't make them more open to changes

I'm a bit of a programming language geek because I like beautiful theoretical things. This is why I keep an eye on OCaml, Haskell, Erlang, Elm, Clojure, etc. I sometime share the frustration with Go being verbose and naive. But I also needs to get things done, and want my code to be readable, understandable and maintainable in 10 years. Go is an interesting tradeoff, betting less on the advances of PL theory, and betting more on good engineering (the excellent work on the garbage collector being a good illustration).

Yes, I'd like some kind of shortcut for error handling (like the try! macro in rust), I'd like to be able to define custom generic functions and containers like the built-in ones, I'd like being able to declare non-nullable pointers, and I'd like to be able to create "share-nothing" goroutines with a "let it crash" philosophy. But I'm not willing to have these things if they break the language main benefits, especially its simplicity.

Maybe the Go team is not open to the changes we're discussing because they just don't align with their goals?

"Go actively tries not to. There is no pattern matching, there’s no borrowing, there’s no pure functional programming, there’s no immutable variables, there’s no option types, there’s no exceptions, there’s no classes, there’s no generics…. there’s a lot Go doesn’t have."

But one of the things it does have is users. It's almost like language popularity is strangely orthogonal to that laundry-list of ideas that the language theory community have invested a great deal of time in. I'd hypothesize that for someone who is excited about those ideas seeing use (and therefore somewhat justifying the time invested in pursuing and polishing them), a language like Go skyrocketing in popularity relative to its age (http://www.infoworld.com/article/2981872/application-develop...) --- a language that looks at decades of PhD thesis work and says "tl;dr we have work to do over here" --- must be downright infuriating.

Good points, and also correct answer. Identity is hard to question. But when you try Go without prejudice, it's just fun (and productive) afterwards.

I work in Go full time, so i don't know if that counts as without prejudice. But I do not think it is fun or particularly productive (if measured by the amount of stuff i can get done in a particular set of programming time). I'd say I haven't used a language I was less productive in or that I enjoyed less since Java 1.

What I think Go has done for me, is crystalize a belief I was already leaning towards, which is that a language being productive or fun is a lot less important than standards cutting through the issues that don't matter.

Not arguing about the best way to format code, or which test library to use, or how to share memory across threads is what makes Go valuable. It is implied that the language has to be this bad to achieve that, which is the open question to me.

With golang, it is incredibly easy to get productive fast. It's like modernized, safe C with good standard library and trivial deployment. Those are pretty good selling points for getting stuff actually done.

Using Haskell for similar stuff is more tedious, even if a actual coding is more fun. I can see (and sometimes feel myself) the cognitive dissonance here.

I think the issue here is that you're comparing Go to C and Haskell.

C is decades old. Haskell was designed to help you write correct programs, rather than simplicity of use or productivity (or that's how I'd characterise it).

If you compared Go to C# or Java 8 or Scala, it'd probably look a lot worse. Deployment isn't so difficult that Go has any advantage in my experience: install a JVM on the server, ensure your build system is producing a fat jar, run it. Done.

With Capsule you can even make self-executable JARs that have a little shell script attached. Then you can run the program like any other UNIX app. chmod +x and ./execute it. Fully self contained, and can even update itself automatically.

I use C# at work, and I use Go at home. I really do like C#, but there is a reason I am using Go at home. I find I am more productive, and can develop better code faster with Go even though I am very new with Go.

I'm curious which parts of Go you find more productive than C#. Visual Studio slows you down?

> Using Haskell for similar stuff is more tedious, even if a actual coding is more fun. I can see (and sometimes feel myself) the cognitive dissonance here.

I don't think the same could be said for say, Scala or F# which offer many of the same paradigms but in a more flexible way though.

Hate is a very strong word. I don't see a point in "hating". Strong dislike, however, I can see, and I think my reasons for not liking Go are "Go ignores 40 years of programming language research", "Go is a language for blue collar (mediocre) developers" and "that other people were falling for it." I guess I have a similar dislike for every technology which is primarily meant to make the life of the developer, rather than push the end product's quality. I guess I have a dislike for this culture, that has been brewing in recent years, in general. But is that my "identity"? I don't know. All I do when I see these types of technologies, is roll my eyes, and move on; it means I have to be more picky in my job picky when looking for jobs. People are taking this way too seriously.

> I guess I have a similar dislike for every technology which is primarily meant to make the life of the developer, rather than push the end product's quality.

I would suggest that this is short-sighted. After all, the end product is created by the developer. Making the developer's life easier and end product quality are not contradictory goals.

The gap between the premises and conclusion of this argument seems broad to me...

Here's the summary: (leaving out some smaller arguments i.e. scala/rust vs Go language philosophy)

1. Go challenges peoples identity.

2. Challenging peoples identity makes them respond emotionaly not logicaly.

3. Other people are being deceived into liking Go.

4. People become more vocal as they attempt to sway the deceived from their erroneous path.

5. (conclusion): Therefore, everyone criticizes Go so much.

Notice all the premises could be true, but they would not strongly imply the "so much" part i.e. "a lot". It would just mean some people would respond more vocally/emotionaly, certainly not everyone.

Anyway, I think there's still some missing premise(s) which would explain why there is "a lot of" criticism for Go, if that is the case - I have no idea as I'm not involved with Go at all.

Anyone care to fill those in for me?

One premise that I think the author is wrong about is #3 (people being deceived into liking Go). My experience is that a number of folks liking Go is due to past experiences and recognizing Go's completely different approach resolves at least some of those deficiencies or the problems those practices eventually led to.

But, I think the main point of the article is that Go's complete 180 on many things challenges the beliefs of some and hence their identity. We see it every time a discussion on Go pops up.

One of Go's selling points is always it's a pragmatic language. But after using it for awhile and implementing a few web apps and APIs in it. I've crossed it off my list for web app or API development. It's great at making standalone CLI tools, however.

I've since moved to using Elixir (erlang) for web app stuff (even some scripts) and I am much happier. I'm not in love with Elixirs syntax, but it's nice and includes meta programming. Elixir is a much more pragmatic language in my opinion. Once you use things like pattern matching (what could be more pragmatic) you can't go back. Raw performance is nothing to write home about but in my use cases elixir does a great job of hitting the sweet spot.

What's the performance of Elixir been like for you? We're looking into it because of the actor concuttrncy model which we think will be much more performant than our current ruby or clojure solutions.

It's great at IO. Period. Get a request, pipeline it, transform it, call out to a database, get some data back, fire off emails, talk to third party APIs....

All of those can be structured as processes. All of those can be independently fault tolerant. All of those can be inspected while they are running...in production. Seriously, for HA APIs or web apps it feels like a no brainer.

I just wouldn't us it for things that are CPU bound, like image processing for example. Try implementing something that is a bottleneck in your system in elixir and then throw some data at it and see how it performs.

Elixir + Phoenix is a real treat for web app devs.

Fantastic. Thanks for the response.

Our use case is talking to an API, doing a little bit of processing then writing to a database. It's all IO with barely any processing (just a few string substitutions to "normalize" the API responses).

What are the rationales underlying your choice to stop using Go and move to Elixir for web app or API development?

In no particular order:

No sane story for request contexts. I got tired of waiting for net/http support for x/net/context.

Coercing Go structs into JSON and vice versus was just annoying enough. I felt like I was paying the price (being more explicit) for static typing without a lot of the benefits of other static typed languages.

and this: //go:generate stringer -type=Pill [https://blog.golang.org/generate]

> No sane story for request contexts. I got tired of waiting for net/http support for x/net/context.

This is moving forward. A package context would probably be added to the standard library and integrated with net/http.Request:


How is this issue solved in Erlang/Elixir?

> Coercing Go structs into JSON and vice versus was just annoying enough.

I had the same feeling when I started using Go (coming from Python/JS, and Java/C++ a long time ago). But then I realised that I have to validate my inputs anyway, even in Python, JS or Erlang. Defining a struct and unmarshal to the struct gives me that for free in Go.

How do you solve that in Erlang/Elixir?

Note: This is from Oct '14

>Obviously, not everyone hates Go.

Well, at least the author saves me the time reading the rest of the article.

Why would anyone think Go and Rust are bitter rivals? They're great tools for different things, with a broad margin of overlap.

Ultimately, they share a space - compiled, memory safe, and aimed at server-side development.

The way they differ is mostly in how they approach memory safety, which gives them different performance characteristics.

Go is about making every distraction from the thing you want to do go away. There's only one way to do it, built in and good enough. Batteries are included. Compiling is painless. Deploying is painless. Just add algorithm.

Rust (which I understand less) seems to be about making a program that does exactly and only what you said, including deterministic memory. The safety is less about a general intent to be safe, and more about guaranteeing invariants that are needed by deterministic memory deallocation. Its natural hunting ground is real time - any program that has to finish things by deadlines.

Rust isn't solely aimed at server space: E.g. we have servo, a browser engine.

"aimed at" and "used for" are never disjoint sets.

Go is one of the fastest runtimes out there, on nearly every platform, produces one clean static binary, fixes the concurrency/async problem that makes other lanaguages so terrible to code in, and has one huge company backing it. But then they miss the boat on simple stuff like generics.

Everyone hates Go because it solves the problems that most other languages suffer from. And if they (Google) make a few improvements it would probably the The Killer Language of Choice out there. But instead they suffer from the elite smugness and won't adapt.

Elite smugness? Hardly. Russ Cox has stated repeatedly that he's not against the implementation of generics in Go. Adding generics to a language is a very complex process and you have to be careful with the method you select because you're stuck with it forever. When they find a proper way to implement generics in Go then they'll do so, but they're not going to be pressured into creating a bad implementation.


And Erik Meijer wrote "Often I wonder if generics are actually worth their weight."


I never used Go, but the main issues seemed to me that Google promised a C/C++ alternative and failed. Instead they made a Ruby/Node.js alternative.

I mean, telling C/C++ devs GC is the hit and parametric polymorphism suck? What did they expect...

Don't know if I'm right, but that's the gist I got from all the comments and news about Go.

While I agree with the premise of the article, I don't think this is why I don't use Go. I don't hate Go, but I also don't think it brings anything new or elegant to the party. Languages like Rust and Elixir are exciting to me. Go just feels like a rerun of everything I've done before.

I've been using Go for several months and love it.

"People shouldn't like things I dislike." --waaaah

I like Go. I've little project https://github.com/beyondns/gotips The essence of Go in some little piece of code:

select { case <-time.After(queryTimeLimit): cancel() <-done // wait fmt.Printf("time out") case err :=<- done: if err != nil { panic(err) }


// https://github.com/beyondns/gotips/blob/master/tips32.md#17-...

I like functional languages but I strongly dislike their communities. Mainly because they treat everything like a nail... Golang on the other hand focuses on solving real problems not inventing things like metaisomorphic multipolymorphism etc...as always technology is fair! Go check out the "real life" projects in go and the adaptation they enjoy.

I would say Go is a very unintuitive language. And not in an especially useful way.

Honestly, it comes across as a language designed by someone only incidentally aware of programming. This isn't an argument, this is the first impression.

At the risk of sounding stupid, and not really having a say in the argument for or against Go, I will say I tried to learn how to program Go on my own by trying to "guess" how to write a program. (A time waster, I had seen code but mainly glossed over it.) The program I tried to write was "Hello, World" and the way I tried to guess was using the Go website's sandbox.

The result: https://play.golang.org/p/oc-cxnjJiI (Best case: https://play.golang.org/p/NJpwhLUPA_)

I'm sure the same thing would happen trying to learn C++ from a compiler's cryptic error messages, but C++ is not Go.

One thing I dislike about Go is the culture or lack-there-of surrounding it. Especially in the canonical Hello World example, which chooses to use Japanese/Chinese language in an unnecessary way. A little presumptuous. Especially since it's used in a one-off sort of way with no explanation.

I also think it's interesting that it's the survivor of the Go and Dart launches, when I never saw the purpose of Go when it was launched, compared to a special set of libraries for C.

There are many good things in go, but some very weird stuff too.

Good things are multiple return values, lack of semicolon, optional braces for if and for, insanely fast compile time.

Bad things are forced curly brace style, complicated function declaration syntax, variable declaration which is too different from C in my opinion (type after the variable name).

I'd honestly prefer a language which is even closer to C or C++ in its syntax, with native maps, sets, queues, tuples, etc (pythonic stuff) without necessarily having templates or inheritance. I put a lot of value in syntactic sugar over overblown abstract stuff. Using plain struct with data oriented programming will be more than enough in most of the cases.

We are still waiting for C++ modules, which obviously might be lagging because C++ has an ISO standard and a lot of existing code which involves backward compatibility, but I think we need a new language that could be faster to compile, just like go is.

Types after variable names are here to stay though: they are in no way something new, and make a hundred times more sense when there is type inference: If writing down the type is optional, then it should go last.

Given that some level of type inference seems to be the future of strongly typed languages, I expect variable ahead of type to become more and more popular among language designers.

I did not like go until I tried it out on small pet project. Now I know how to enjoy it.

Same. I hated the idea of it before I started to use it and started to use some of the tooling (like goimports, gocode, etc) with the go-plus package on Atom.

I think tooling really makes the difference in this case.

Attributing a person’s preferences to identity is just ad hominem. That doesn’t even imply it’s wrong or mean-spirited; it just means that it’s “preferable” to talk about a person’s motives. Very Kahneman.

If you replace "Go" with "JavaScript" the whole blog would also apply. Except there are way more JS lovers than Go lovers out there. And these two groups almost seem to never overlap.

Offtopic: Can we please use "GoLang" for the language, so we can use "Go" unambiguously for the game?

Especially in titles, where there is little context.

I do find the name extremely unfortunate. It's impossible to search for, as "go" is an extremely common word (bad for search engines) and substring (bad for ctrl-F find). I tried searching for shared web hosts that provide Go support and just gave up. Kind of hilarious to see a first-party Google language be impossible to search for.

And the was another existing programming language called "Go" and Google being well Google just stomped on that and moved on calling theirs the same thing. It is a nice benefit of being a billion dollar company.


Using "golang" instead of "Go" nearly always gives the correct results in my experience.

That's true-ish, although it seems unlikely that most marketing departments who would be putting together a web server page would use "golang" over "Go".

Edit: This would be solved if the language was called "golang," which is precisely the original poster's point.

A great many programming languages aren't particularly searchable, especially when searching engines weren't up to todays standards yet. Things have improved, but I remember the dark days when looking for anything C# would shower you with C-related links.

Or how about searching for ".NET"? :)

It should be illegal for programmers to name anything they created ;)

That's like calling for people to specify "Microsoft Windows", to avoid confusion with glass-enclosed wall openings.

I know there was a bit of news recently about a game engine defeating a top-level human player. Beyond that, however, the notion that "Go" references on Hacker News should default to the board game rather than the programming language is absurd.

Articles about windows-the-opening are pretty rare here, so "Windows" isn't ambiguous. Articles about Go-the-game are common, so "Go" is.

It's not even the first programming language named Go. [1]

[1] https://en.wikipedia.org/wiki/Go!_%28programming_language%29

For the game we should use "Go/Baduk" or something like that.

"game of Go" seems simple enough...

i would argue that for most people here Go = GoLang

i had never heard of the go game, before the ai go thing

I don't know what the basis for your argument would be. Go the game and GoLang are both fairly talked about topics in Computer Science, most programmers do not program in GoLang (according to Github), and the AI match was a big deal for Computer Science in general. I would not be so quick to say that for MOST people here Go = GoLang, and agree with the parent comment.

Just because most programmers don't actually program in Go themselves, it doesn't mean they don't know what it is.

I haven't written a single line in Go, and yet it's immediately obvious to me what the title refererred to.

You have multiple people here telling you that their first reaction was not Go as in Lang. The obviousness to you and others does not prove the title is unambiguous to most. Here, we're trying to propose a solution that aims to eliminates ambiguity for the majority.

I believe we are still in majority. Nothing has proven otherwise

The majority in what I said is = [people who treat Go as GoLang first AND Go as the game Go first] = the set of all people reading hacker news minus those who don't know either Go. Writing GoLang removes ambiguity for this majority. My first comment on this subthread has shown that neither you nor any other poster has proven that Go = Go first for most. Nothing you or any other parent comment including my own has proven either of Go = GoLang first OR Go = Go the game first for the majority of people.

It depends on the context, too. If I read a headline saying something like "Go is awesome for your brain", I'd be 95% sure it refers to Go the board game. When the headline reads "Why everyone hates Go", I'm pretty sure it can't be about the game. I don't think I'm being an exceptional individual - humans in general are very good at taking hints from context.

I have a strong feeling that there is a marketing campaign going to promote Go. It is promoted so hard that it became annoying. :(

The main problem with Go, and this is a deal breaker for me, is that it forces opening curly braces onto the same line, instead of putting them on a line by themselves. This is clearly wrong, and flies in the face of curly good taste.

If it's clearly wrong, can you articulate a reason? There is at least one (mild) argument in favor of opening a curly brace on the same line: code takes up less vertical space, allowing a programmer to view more of their program on a given screen at once.

I use both styles in the same code:

  if (simple_condition) {

  } else {


  for (long and stuffed;

  if ((complicated ||
      && condition)

  void function()
In an if, all the "else if" and "else" clauses have to follow the same style. If any is braced, they all have to be.

By the way, is grandparent kidding about Go enforcing this?

The only language I can think of which enforces curly brace placement is Awk. (And only in its pattern-action pairs):

   BEGIN {
        if (foo)

   /regex/ {   # can't move this curly to next line

RATIONALE: why the two styles? Why

  if (simple_condition) {

  if ((complicated ||
      && condition)

Simple: it's because in both cases, the "code" follows a previous line from whose first non-whitespace character it indents by the indentation level:

  if (...

This is just wacky:

  while (blah
         blah) {
"code" isn't "indenting off of" anything. It is not related to the indentation of "blah" in any way, but appears to be "deindenting" from it!

So, rather than dogmatically doing one thing or another, it's better to consider all the alternatives, their relative advantages and disadvantages, and integrate them into an elegant whole.

One reason I love Go for it. Look, it will prevent the replies you got, while I am thinking about solving a problem. :)

Go forces one format. Although you definitely can ignore formatting your code and just compile it. It won't fail.

Many, many people disagree with your basic deal breaker, completely unrelated to Go. E.g. the Linux kernel uses this brace style.

Now I'm wondering if I've just been successfully trolled.

why everyone loves clickbait

ML is also simple, pragmatic and from the '70s.

I like Go but I hate my self for it.

Hating oneself is the highest form of love. -- Bill Maher on gay Republican politicians.

Very sorry to make an aesthetic complaint, and Raleway is a fine font for certain applications, but blogs that use low contrast fine raleway for the body text just kinda make me want to read something else.

I would burn Go with fire and salt the earth because it's the bloody compiler will refuse to compile my valid code if I have unused imports or variables. It makes programming in Go a terrible experience and that's why I won't touch it.

You'll love goimports then.


Hook it to your editor's save command and never worry about imports again.

On the other hand, stop leaving unused variables around...

I hate debugging someone else's code that has unused variables in it as much as this guy seems to hate the go compiler.

Any normal compiler usually allows overriding these options. I normally write Haskell and it has it all: unused variables, unused imports, name shadowing, non-exhaustive pattern matching, everything. But these things are warnings in my dev build and errors in the release build. That's a sane way to do it.

Except some people wouldn't enable -Werror, and the quality of Go code would suffer on average.

Plus, now your compiler has options.

Yeah. I'm a fan of mandates when it comes to things like compiler options. Everyone should just suck it up and work with the same constraints. Warnings are just errors without balls.

> On the other hand, stop leaving unused variables around...

I don't think there's any problem with doing that. I use a linter to stop me committing code that has unused variables in it, and to highlight those kinds of style issues in my editor so I'm aware of them. But for a compiler to refuse to run unpolished code in development is just bad design.

It's as if Go's designers took the hubristic or naive view that all code would, in an ideal world, be typed out perfectly first time, as opposed to being gradually hammered into shape through trial and error. This is worse than a design flaw, it feels like an active imposition.

This to me is one of it's benefits - uncommented, unused variables shouldn't be in code, and I like that the compiler is actively preventing me from being lazy and creating cruft that's simple to remove.

I think that behavior is annoying, too. I've wonder if there's a way to tell the compiler to generate a warning for unused variables instead of just erroring out.

No there isn't. Because Go loves to show you the middle finger.

Thank you for your constructive comment and downvote

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact