Go is an interesting shift in language design, basically discarding many modern trends and techniques and returning to a much simpler paradigm. It's a totally valid approach with lots of merit — complexity can be a killer. In addition, the concurrency primitives, decent stdlib and tooling make Go pretty great to use in some respects. It's likely to be well-supported for a long time and is a suitable tool for many tasks.
On the flipside, using it often feels like a bit of a slog. Error handling is simple (good) but repetitive (bad). Keeping generics out of the language avoids complexity (good) but results in repetitive and awkward code (bad). Lack of features like pattern matching and higher-order functions makes some code irritatingly tedious to read and write. And so on.
Point is, it's perfectly valid to look at these decisions and say "I don't like Go because it is missing these features", as much as it's valid to say "The simplicity of Go is a useful feature". Ignorance is not a prerequisite for disagreement.
So please have some respect for opinions which differ from your own, and think about offering something a little more constructive than insults.
Aside, I use and enjoy languages other than Go; it is simply a tool to solve problems, and I don't want to detract people from using other tools. We all develop opinions with regards to what does and does not work well. I never intended to devalue others' experience or perspective. I was simply pointing out that many people seem to not have suffered through enough bad work experiences to appreciate Go's main feature of simplicity.
If you haven't run across horrible, insanely overcomplicated, code written by those that think they are the top 1% intelligence-wise, you might not appreciate Go. Likewise, if you write horrible, insanely overcomplicated, code and think you, yourself, are brilliant, you probably won't appreciate Go. If you only work alone or on small teams and projects, you might not appreciate Go.
(They even have a codewalk that mentions this in its introduction)
The size of an array is part of its type
If one declares
var arr10 : array [1..10] of integer;
arr20 : array [1..20] of integer;
then arr10 and arr20 are arrays of 10 and 20 integers
respectively. Suppose we want to write a procedure 'sort' to
sort an integer array. Because arr10 and arr20 have
different types, it is not possible to write a single
procedure that will sort them both.
The place where this affects Software Tools particularly,
and I think programs in general, is that it makes it
difficult indeed to create a library of routines for doing
common, general-purpose operations like sorting.
People who complain about the lack of generics in Go are making the same argument that Kernighan made against Pascal viz. that it is tedious to write library code in the language.EDIT: Also it is not uncommon for a feature that is deemed essential by some to be thought of as adding too much complexity by others. For example,
"I've seen [visual] editors like that, but I don't
feel a need for them. I don't want to see the state
of the file when I'm editing."
said Ken Thompson [2] when comparing line editors like ed to visual editors like vi or emacs.[1]: http://www.lysator.liu.se/c/bwk-on-pascal.html
[2]: http://web.archive.org/web/20080103071208/http://www.dcs.qmu...
The Extended Pascal ISO standard which does include dynamic arrays is from 1990.
Turbo Pascal and other Pascal dialects also had them.
Write your own macro-assembler constructs and you're off to the races!
So, something like that?
Interfaces, man. They're better than you think.
Data structures are the obvious use for generics. There are also things like monads and so forth, used for example in Rust's result type.
The Go authors were following a practice that seemed like a good idea at first, and they've now admitted was probably a mistake... i.e. if your package is mostly about a single interface, name the package something informative, and call the interface type "Interface". This works relatively well from calling code, since it'll be referenced as "sort.Interface", but it makes the documentation for the type potentially confusing.
This Sort.Interface thing is indeed safe and performant. On the other hand its not a solution to the problem we're discussing (that, to quote the parent, due to lack of generics "it is tedious to write library code in the language"). You still have to implement it all the time for all types despite having identical implementations.
So this doesn't show how it's not tedious. It just shows that it can be done in some way, which nobody doubted.
Complexity is also the mind killer. However, it kills with ten thousand cuts, not with one fell stroke. This is why the prideful are even more vulnerable!
This is a very memorable and useful quote. Thanks for saying it. It deserves to be a classic, in my opinion.
This is only true with identical utility functions for all participants. Rational decision making means each actor acts with perfect information about expected utilities of all options and chooses the option that maximizes their own realized utility. Rational actors can easily disagree without ignorance, since rational actors can have different utility functions.
While there are some questions where ignorance of each others utility functions could produce disagreement, I can't think of any where it is necessary for disagreement.
You'd also have to be profoundly naive to ever assume entirely rational decision-making out of humans, though I get the sense that a number of those words must mean very different things to you than they do to most.
Here's the deal -- all programming languages are just tools. Go's great because it's small enough to keep in your head, and simple. It's fast. It promotes composition. And it has sane concurrency. And quite honestly, I am more productive for the things Go left out then it includes. That's not to say Go is a perfect (e.g. a 'real' debugger option), and it doesn't have to be. If you love Rust, or Ruby, or whatever, great. The programming language landscape is not a zero sum game.
tl;dr Go's a fine tool to get stuff done for a large set of problem domains.
This. And the additional effect is that you can keep more of the problem domain in your head as well. I've been in this game a long time, and my experience has been that the simpler the dev tools, the more likely the programmers working on a particular domain will be SME's in that domain.
Whether you write it in Ruby, Java, Go, Assembler really doesn't change this. It just means you may take longer to do it.
And your logic falls apart. If simple dev tools translate to greater productivity then how do you explain the proven benefits of IDEs with all of their "complex" features.
While I mostly agree, the flip side of this statement is, the language then does not automatically take care of things that then you have to keep in your head while you're solving the problem.
I guess this is the underlying trade-off people make when using "higher-level" or "lower-level" languages. More "powerful" languages do more for you automatically, but you need more up-front investment in really understanding the language and applying it to the problem at hand.
And since we are all individuals with individual preferences, whatever choice you make is totally valid for you. It does not make sense to look down on the choices of others. On the other hand, there are some concepts that really are well-understood enough and apply to a large spectrum of languages. These should see widespread adoption, and it does not make sense to deny this either.
Sure, language like Haskell or Rust have a ton of great features and automagical things but I disagree that they are easier to use. One has to keep far more in your head writing Haskell than Go, a clear indicator of this is the difficulty in learning the language. Like c, you can learn Go in a weekend easily.
I am not saying those others types of languages don't have their own strengths, just that I disagree with your assessment that their features provide a lower mental load.
Obviously said person would not be an expert, but I've watched competent programmers try to learn complex languages like Haskell and Scala; there is a far more complex mental model that one needs to build before they can use those languages specifically because of all the automagic that happens in the background.
We'll need to define criteria for "useful program" but I believe most people could write useful programs in most languages in a weekend.
> I've watched competent programmers try to learn complex languages like Haskell and Scala
> far more complex mental model
I think its more that those languages are different, not that they require a more complex mental model.
A complex recipe rewards a chef with exceptional results if they follow it perfectly, but also presents more opportunities to fail. A simple recipe might not offer the results but it should be easier to produce with a lower chance to mess up.
I think the concept generalizes here.
Right, but remember simple doesn't necessarily mean easy. The reason I use functional languages is because in my experience they handle complexity better.
> A complex recipe rewards a chef with exceptional results if they follow it perfectly, but also presents more opportunities to fail. A simple recipe might not offer the results but it should be easier to produce with a lower chance to mess up.
> I think the concept generalizes here
I of course mostly agree to both of the above, but I think you are mis-characterizing functional languages such as Haskell which are simple but quite different from languages most are used to.
Agreed, which is why I prefer to implement complex ideas in Haskell. It catches more potential errors than other languages.
I don't think that's really true. I think that's a subjective description of a feeling whose presence or absence depends not how any objective difference in the quantity of things that you need to keep in your head with either language, but with how well each language fits one's (subjective) intuition.
Mental load isn't an objective feature of a language, its a subjective feature of a particular programmer's relationship with a language.
Go's error handling is to put it nicely a joke and requires a lot of effort to manually check every single error condition that may arise. Exception handling makes life exponentially simpler. You can ignore, group and delegate errors at any point which is hard if not impossible to do with Go.
As a fellow Go coder, I'm actually stunned how much I can get done without a debugger nowadays.
(by the way, you might have misread it. I think he didn't mean "generation of masters" as "old smart people" but probably specifically the creators of Go, since they happen to include Rob Pike and Ken Thompson - two people who had separately created the B programming language (immediate predecessor of C), co-created Unix at Bell Labs in the 70's, co-authored a famous Unix book with Kernighan (of Kernighan and Ritchie fame), authored UTF-8 together, etc. They happen to be actual old masters.
They created Go in 2007, from what I heard cleaning up a lot of their old mistakes along the way.)
Being created by Pike, Thompson, and whoever else does not in and of itself make Go better than any other language. It also does not make it immune to criticism in such a way that you should brush off anyone who has anything negative to say about it.
which is why I called your parent useful and informative.
I respect the creators of Go deeply, because they have been so formative of the industry. It's like being an electrical Engineer, and having Nikola Tesla make a suggestion -- I might not understand all of the lessons, but there's a distinct possibility that these guys are addressing problems I don't yet fully understand.
The guys who designed Go have not designed any other popular languages in the decades between C and Go. They have not produced any modern developer tools or toolchains. Rob Pike's last language before Go was a quasi-DSL called Sawzall, which is a Google internal language for logs processing. I had to use it when I was at Google and frankly, I would have preferred other languages to have been used and didn't find the stated reasons for its creation to be convincing.
If you want to talk to someone who has more modern, relevant experience in language design, go talk to someone like Martin Odersky (Scala) or Andrey Breslav (Kotlin). Andrey in particular has my respect because whenever a language design point is queried he has a well thought out reason for it being that way, often backed by evidence from other languages like C#, Scala, Java, functional languages etc or experience of building modern developer tools like debuggers and IDEs. Both things that Go has a notable poverty of.
In contrast, the justification for Go's design decisions very often come across as arbitrary, or very specific to Google's own codebases. For example Google's C++ style guide bans exceptions, partly because writing exception safe code in the absence of garbage collection is very hard. So not having them in Go won't seem like a big deal to many Googlers. But Go is GCd so that rationale doesn't apply, and the others offered are weak.
Same for lack of assertions. Google has a lot of very, very large slow starting servers and unfortunately at some point some of the engineers on these projects decided that assertions were evil because they had some outages caused by an assertion being hit frequently, causing server restarts. Some code bases there ban assertions as a result. Of course this has a habit of converting a noisy, instantly detected problem into one of silent data corruption or garbage results instead. But it's easier for SRE teams there to measure uptime and response latency rather than correctness of results for obvious reasons, so a bias towards "up but wrong" rather than "down" makes internal political sense.
This of course does not apply to many, many other codebases (in particular, codebases that have exceptions!) and the Go FAQ freely admits that assertions are highly convenient. But the language doesn't have them anyway, because hey, Google C++ sometimes decides not to use them.
It surprises me that you say this, since we (the Go team) spend a huge amount of time and energy talking about our design decisions. But you must have missed it, because the examples you give are wrong.
> For example Google's C++ style guide bans exceptions, partly because writing exception safe code in the absence of garbage collection is very hard. So not having them in Go won't seem like a big deal to many Googlers. But Go is GCd so that rationale doesn't apply, and the others offered are weak.
The rationale for not having exceptions in Go is not about safety, but rather readability. When you're programming with exceptions you need to keep in mind a second hidden path of control flow.
I think you similarly mischaracterise the argument against assertions. In essence, the real reason is that failed assertions produce terrible error messages (that's why Go's testing framework doesn't have them either).
While you're talking to Odersky, ask him about Go. (He said: "I like a lot of the design decisions they made in the language. Basically, I like all of them.")
So ? Developers are completely used to it. Every time there is a conditional statement e.g. if/else we have to think about the other control flow. Likewise every time a method calls another method. And if that method is in a different class then you again have completely lost visibility. Developers are constantly dealing with control flows that go everywhere but straight down.
Java is the 2nd most popular language in the world so pretty sure developers have managed to cope with exceptions just fine.
None of that is what I'm talking about. In each case you mention here, it is possible to trace execution by following the code. Each statement passes to the next statement in the block, or—in the case of a branch—very obviously skips to another block or function.
Exceptions provide a second parallel path of execution that may or may not be followed, depending on decisions made in places you know nothing about.
> Java is the 2nd most popular language in the world so pretty sure developers have managed to cope with exceptions just fine.
Arguing "it's popular therefore its good," is a waste of time. Some people obviously like exceptions. I'm just stating the reason Go's designers decided against them.
The arguments about assertions is a typical example of this weakness. A failed assertion in any reasonable runtime and even in google3 C++ produces a stack trace and a log message indicating what assertion failed. It's then usually easy to go read the code where the problem was hit and start debugging.
In contrast, I find typical Go code to be an unreadable mess of nested if statements and C-style return code propagation. Information is routinely lost and errors ignored. When something goes wrong you don't get a convenient stack trace showing exactly how the program arrived at the place where the failure occurred, you might if you are lucky get a generic error message indicating the general subsystem where something went wrong, or if you're very lucky a log message, but several big Go programs I've seen didn't bother with exhaustive logging on error paths and were difficult to debug as a result.
Compare to other languages (nearly all of them) which have exceptions: I've never once been confused or found code hard to read because of the use of them. That's just not a problem I recognise. But I've benefited from them more times than I can count.
I didn't know Odersky said that. I think that's very polite. Regardless, the language he designed looks nothing like Go, so I guess if he really likes Go's design decisions he has decided that his own language got it all wrong. I don't think he's really decided that.
Ignorant might not mean stupid literally, but it still means "you don't know about programming languages" in the context of the comment, which is also bad.
Being a master might not mean you are old, but the masters we're talking about here (Brian et al) are ALSO old.
And saying that you're "ignoring negativity" if you ignore complaints about Go means that you're labelling them as whining or coming from "negative types" instead of accepting the possibility that it can be actual valid criticism.
The crux of the issue is that Go is a local min in a field of possibilities, you may value differently the attributes of various programming langauges which would lead you to some other alternative or local min. I am not passing judgement on others for doing so, but also please be brave enough to admit your ignorance as to why some of us settled where we did with Go. I willingly admit I am ignorant as to why people think other languages are a good idea for general use.
What one means and what one writes/communicates can be two totally different things. The "I know because I wrote it" is a valid argument regarding intent, but doesn't hold the same power regarding what the written thing means to others who read it.
>The crux of the issue is that Go is a local min in a field of possibilities, you may value differently the attributes of various programming langauges which would lead you to some other alternative or local min.
Why would one want a "local min" though?
If anything one would prefer the global maximum or at least a local maximum.
Or is the "min" meant in some dimension that one would actually want to minimize?
Note: Rust actually has a chance because it's simple compared to its competition: modern C++.
Of course, you pay the tax somewhere else and that is code duplication. You see this in Go due to the lack of generics, which often results in duplication of code for different types or reliance on reflection (which is slower and can lead to runtime errors).
This is not a critique of Go, just to point out that it is a trade-off, and there isn't necessarily one right answer.
For you...
It depends on what kind of code you are working on. If you work a lot on numeric code (e.g. in machine learning), you want to make it easy to specialize on e.g. 32-bit or 64-bit floats.
Also, since only built-in types are generic, you cannot implement other containers (you never need binary search trees?) in a safe manner.
So, yes, the lack of generics is a frequent issue for me.
I only point this out because I've seen a lot of Go programmers defend Go by saying parametric polymorphism is only really important in particular niche domains, when really they want to say that Go only focuses on a particular niche domain where it isn't important.
The point I am trying to make is that adding some features from other languages doesn't provide sufficient value without also adding other features. Adding all of them can make the language significantly more complex that you wonder whether the benefits gained are worth it.
Since proper error-checking in Go actually requires doing by hand what a pattern match would have done anyway you're not simplifying anything for anyone by omitting them; you're just making it harder for the compiler to provide compile-time checks.
A pattern match is basically a switch statement. Go already provides the latter so the language would not need to become more complicated.
It's fine for languages to embrace those features, and be what they are, and it's fine for Go to reject those features, and be what it is. We don't need "one language to rule them all".
Don't get me wrong, I like generics. I think they would be a nice addition to Go. But I understand Go designers when they try to be conservative about it. I like that they only add features when it's absolutely obvious that the pros overcome the cons.
Lisp is a very simple language conceptually. The problem is that it allows you to build insane amounts of complexity in a very "free for all" way. No "one sane default way to do it".
The problem is now how complex a language is, but how much needless complexity it allows you to build yourself.
Go seems great because it doesn't easily allow you to build needless complexity. Though I've never coded anything meaningful in it, so my praise for it would be armchair thinking...
For myself, I still like it, a lot. To the point that the more I learn of it, the more I'm confused on how it hasn't taken off better.
Most of it are not primitives though, Common Lisp only defines 25 special forms. Guess how many keywords Go has?
For example Common Lisp provides support for complex numbers and operations for them. These operations are 'primitives' in the language. This is unrelated to 'special forms'.
Any Turing-compelete language allows you to build arbitrarily much needless complexity. I don't see how it's a useful metric at all, except to say, "Well, this language isn't quite so horribly stunted that you can't even produce a nonterminating program."
If you want to talk about how easy it is to build needless complexity— well, I've yet to see a programming language that knows the difference between necessary complexity and needless complexity well enough to allow the former and prevent the latter. Rather, languages either let you build complex things easily, whether you need that complexity or not, or they just make it a right pain in the ass to accomplish anything.
Personally, I prefer the languages that let me express the complexity of my problem domain easily; sure, I could use them to make things more complex than they need to be, but I don't, because to be quite frank that's just part of being a competent programmer.
> Every single abstraction has a price in complexity.
I think the whole point of abstraction is to lessen complexity; wrap up many different things into one thing that's easy to reason about. Very few languages support creating good abstractions, unfortunately.
Abstraction lessens complexity, and also adds complexity.
Take monads in Haskell, for instance. Let's oversimplify and say that absolutely everything is done through monads. Great; we've now wrapped up many different things into one thing that's easy to reason about. And when I want to do something, I don't have to think at all - I just reach for a monad.
And then I have to think, because now I have to figure out how to make a monad do the specific thing that I actually want it to do.
Or I'm reading the code, and yes, that's a monad, because it always is, because everything's done through monads. But what is this monad at this location in the code actually doing? Well, I have to work my way back out of abstraction to concrete in order to understand that.
One way to think about this is abstract art. As art gets more and more abstract, at first I can't tell whether I'm looking at a blonde or a brunette. Then I can't tell whether I'm looking at a male or a female. Then I can't tell whether I'm looking at a human or a chair. And finally, I get to the point where I'm looking at a painting that could be anything, but it's impossible to say what it is. Abstraction has proceeded to the point that communication (between the artist and the viewer) has been lost. In the same way, abstraction in code can proceed to the point where communication between the author and reader is lost, and then it takes a lot of work to wade through the layers of abstraction to find out what the code is actually doing.
When someone talks about a language, I'd rather they talk about what exactly it is the language simplified and where it hid the rest of the complexity. One can only simplify a Turing Complete language so much before the it starts running up against the limits of Kolmogorov Complexity. After that point, the best we can do is shuffle it around - under the bed, or under the sofa, or inside the closet, or into a corner - depending on each programmer's preferences.
When people talk about abstraction for example, they really mean reducing mental complexity. The pro is that we can reason about a larger percentage of our programs by being able to fit more code into our limited working memory. The con is that something other than our brain (e.g. algorithm w) has to do the heavy lifting. With abstraction, all the little details (the complexity) still exist somewhere, we just don't have to look at most of them.
But most of the time, we are abstracting away something specific in order to make something else more concrete and less obscured by irrelevant detail, hence reducing complexity.
Of course abstraction can go wrong, because sometimes we abstract away things that are very relevant, perhaps in futile pursuit of future code reuse. But having the tools for abstraction does not make abstraction go wrong. We do.
The marketting muscle that was put behind Java certainly helped it in its time. Same for the actual market that backs objective c.
C probably benefited as much from the open distribution as it did anything else. Combined with a relatively high quality compiler that was heavily distributed (gcc), this can not be understated. The only languages that were as highly distributed were probably the various BASICs, and there are obvious reasons to fall off of those at some point.
So, you can blame lisp's lack of popularity on its complexity. I am not so sure that is a good foundation, though. I feel it is as much lack of a high quality distribution of it as it is anything else.
Though, highly on topic, it should probably be noted that the approachability of the original C Programming Language book that is making so many people excited about this book probably had a very heavy influence, as well. I am not so sure a book can have as heavy of an influence in today's environment, but I think it would be foolish to discount the amount of influence a publication like this could have had back in the day.
GCC certainly contributed to C continuing to be widely used.
That said, you are definitely correct in C's early popularity. And that probably contributes more heavily than later items. (There is a term for this, but I can't remember it right off.)
Before UNIX became part of the enterprise workforce very few cared about C.
OK, not a big believer of the "Blub" theory, personally - every language has its place in a continuum of dimensions that are more than just technical, and I actually like Go overall. But "lack of generics" is definitely not the same as "simplicity. Not in the decade we live in.
> But "lack of generics" is definitely not the same as "simplicity.
It's not literally the same thing, but it is an aspect that keeps Go simple.
Yes, speaking for myself as someone often in the position of defending Go on HN (even though as a computer language polyglot it isn't part of my personal identity), I also speak several other languages that do have generics in them, along with substantial usage of the "dynamically typed" languages, and most relevantly, including reasonable fluency in Haskell, a language where the generics are so deep and fundamental they aren't even given a name, they just are. What Haskell calls "Generics" is actually more like what other languages call "reflection".
Yes, there are a ton of programs that you can usefully write without "generics", especially since interfaces are about half of "generics", and arguably the more useful half in general. Yes, there are a ton of programs that you can't really write without them. We could do with a lot more sensible discussion about which programs are which and a lot less "Oh, you think it's OK for Go to not have generics? Well you must be an idiot then." (e.g., my frequent observation that if you need a rich numeric hierarchy you really need generics... but those cases really are exceptions compared to programs that are just fine on integers and floats, and, frankly, in many cases just fine on integers alone.)
I like Go overall, but on balance I would prefer a slower compile-test cycle to have more language feature support.
So, are you sbt as in:
? I don't think i've seen a build tool posting on HN before, but now i have, i'm not surprised it's a Scala one.
Generics I still miss every single day.
But not enough to stop using Go. It's pretty much C with interfaces, a garbage collector, and safety. What more can one wish for?
It just creates the code for you, then you commit it. Easy enough.
Except that it does not provide the same thing. If I provide a package with e.g. a container datatype, I would have to generate for every possible data type that any user wants to put in the container.
Obviously, that is not going to scale.
gen is a good contribution, but it only works for a subset of cases. E.g. I follow a comparable approach in my Java library for finite state dictionaries because Java does not provide generics over primitive types (luckily, that is a closed class). But it's less than ideal.
An analogy would be the "deriving" system in Haskell. It doesn't replace the generics system, it just complements it.
func foo() error { return errors.New("whoa!") }
func bar() {
_ := foo()
// onward!
} try {
foo()
catch {}
In other languages. That's not a problem, that's the computer doing what you explicitly told it to do.There are many situations in which you want errors to go unhandled and bubbled up to some common error handling logic.
Exceptions IMHO are vital. They standardise error handling behaviour across your application and provide flexibility in when, where, and how you handle groups of errors.
Though simplicity of the language is important, I feel that the ability of a language to manage complexity is more important. It is probably one reason why many people (myself included) have some issues with design choices made in Go.
A bit like you can select different languages in Dr. Racket http://docs.racket-lang.org/drracket/choose-language.html
That's not my experience with Go at all - it provides less resistance to getting code written than any other language I can think of offhand.
The "not quite a field" of programming, has a famous history of being full of smarmy naysayers being spectacularly wrong. It's no wonder that the few of us who aren't bratty and quickly judgemental tend to become famous and successful. (Nor that a famous blogger once said that everything he needed to know about managing programmers, he learned from the book, "How to Talk to Your Five Year Old.")
So maybe you'll excuse some people for not simply assuming that the masters are right just by virtue of who they are.
While so many people are complaining about what it doesn't have, there are things it does have that, while not individually unique, are actually packaged into a unique bundle. Particularly the fact that it is a traditional imperative language. If you (like me!) don't mind picking up Haskell or O'Caml or Erlang to get weird features, it might be hard to understand the appeal, but for many people Go is the first time they've seen these features without having to drop almost everything they know about programming on the floor in the process. This probably explains some of the breathless excitement it sometimes engenders... it's the same breathless excitement that people will sometimes have when first using those other languages.
(And, yeah, the traditional imperativeness does bite a bit. I'd love to be able to assert that a goroutine is fully isolated from everybody else's memory. In practice, I'm not having any trouble with that, but, then, I've got 7 years or so of Erlang under my belt so designing isolated processes that work together via clean interfaces is something I've got a ton of experience with from the most rigid language on this topic there is. YMMV, and I really mean that... you certainly can blow your foot off in Go, isolation is only convention, not enforced.)
The problem is not really what Go does not have, it's that often fallacies are used to react to critique on Go. Another one that pops up very often is 'you just have to use it for some time to understand why Go does not need it'.
This is of course nonsense. Anyone who has programmed C and C++ knows the advantages and disadvantages of generics. And despite the disadvantages of a particular implementation, most people want still want generics for good reasons.
Even if you like Go (and I do mostly), it's ok to say 'sure, that is a weakness in the current version of Go'.
That said, since you mentioned it, I'll reiterate what's in that link to observe that "Go doesn't have generics" is a half truth. (And I don't mean "lie"... it has non-trivial truth in it. But it is only a half-truth.) Generics are a complicated concept that encompasses at least "generic data structures" and "generic algorithms"; you can slice and dice in other things, too, but it certainly has at least those two aspects. The former I freely admit is an uncovered case, and I still believe is something Go needs to address sooner or later. The latter is covered in Go via the interfaces.
I think the reason why Go in practice doesn't need a lot of generic data structures is that its core use case, concurrent network servers, has an awful lot of byte streams flowing around, and, lo, the code I'm converting into Go has a lot of byte streams flowing around. A bajillion "generic data structures" don't much help with that use case. (Now, the natural contrarian argument here is to talk about how you might need them someday, but, seriously, you probably don't need them all the time. If you do... don't use Go.) The "generic algorithms" concept is incredibly useful, but, lo, Go actually supports it fairly well. On first read of the Go feature set it's really easy to blip over the "implicit satisfaction of interfaces" and think it's an irrelevant parlor trick, but in practice it's really very useful in surprising and profound ways.
There's authority, and then there's deep domain knowledge.
If I was in the market for a bicycle, and Lance Armstrong had built one, you better believe I'd at least try it out. And even if I didn't entirely understand why he built it the way he did, I'd probably just assume he knows WTF he's doing.
Note that the whole reason this HN thread exists is not because some random book on Go is being published, but because Brian Kernighan's name is on the cover.
Fame is a good enough reason to give things priority when it comes to checking it out. But it is not a valid reason for saying why it is good to begin with. There's a difference between saying "I might buy this book because it is written by X", and "This book is good since it is written by X".
I don't feel like they ignored them they are basically saying they think they have a better solution.
If it doesn't become popular, I think they will just let it die. If they start trying to make it popular, I think there will be a big push back from the great unwashed masses of people who want obvious features and then it will die. Only time will tell.
Remember when they were building Chrome and how quickly they iterated on it? That was awesome to behold! Maybe a slow pace and a smaller user base is better for developing a language, but if that's the case then I guess I'll just wait another decade before really investing time into Golang.
So anyone who likes Go is deceived? Why use words like that? How about just saying GO isn't for me. Saying any more is just you imposing your opinion on someone else and devaluing them.
It's mostly the wisdom of the eighties. Today's professionals have better options.