Why Go Is Not Good (2014)
yager.io
yager.io
It aims to be a pragmatic language. But IMHO the anemic nature of the type system is a practical handicap that they have made a point of pride out of not addressing. It leads to boilerplate code and fragile code.
I am no academic language snob -- I like Rust, and have been known to like me some C++ templating, sure, but I can understand a critique of complicated type systems that laypeople cannot understand. But after my brief exposure to Go, I was very very frustrated. I don't think it really solves the problems it says it's solves.
As you say, the Go developers seem to have developed a kind of bunker mentality where they interpret legitimate criticisms of the language design as personal attacks, and respond by wearing Go's shortcomings as a badge of honour.
It's not, I think, entirely healthy.
But there are many types of static analysis which accomplish similar (or more dramatic) goals than what can be down with type analysis, and the simplicity of a language makes those kinds of analyses more reachable. Examples: gofmt and gofix.
I think it's amazing what kinds of magic can be encapsulated with the type system, but my experience doing software is that complex types often end up being a hairball which is very change-resistant. Go's emphasis on lifecycle support for large programs may point us to new kinds of tools and methods. Whether those tools and methods end up being able to be encompassed by type theory is an open question, but it looks to me like Go is aimed in a great direction to raise the questions.
Rust, while lacking in various aspects as any v.1 release would, already has means of extension. A library can mostly replace a lacking feature while playing nice with the rest of the ecosystem by use of the type system and the macro system.
Roughly the same kind of extensibility is possible in Python (some later language features first appeared as approximations in third-party libraries) and even Java (where a kind of code post-processing is possible via annotations).
Unfortunately, it's unreasonably hard in Go. All you got so far is un-hygienic macros, slightly better than C #defines.
This is sad because a number of other ideas in Go are right and well-implemented.
Go's target audience are 2 groups: people previously writing stuff in C/C++ because they didn't have much choice unless they wanted to bring a shitton of dependencies, but in reality didn't want the complexity this brings, and people coming from scripting languages like Python and Ruby. And for these things, go is pretty damn good. It has it's downsides - like any language, but it works. It's strongest point however is it's standard library with 'modern features' and transparency. For me it was the first language where diving into the source code of libraries - even the stdlib - was so effortless and has become a completely normal thing to do. In C/C++, the most you do is dive into the headers, and in the latter case, this is not always a good idea if you want to keep your sanity (hello Boost).
Rust could gain traction the moment it finds a market, and few high profile projects written in Rust that are widely used. But right now, I'm not aware of any.
Nope. I like Go because:
* Interfaces
* A sane, fast, build system
* Concise syntax, mostly
* Garbage collection
* Excellent concurrency support
* A (for the most part) well-designed standard library
* Optional semicolons
* Compile-time type-checking
* Static binaries
I like Go because of the features it has, not because of the features it doesn't have.
On balance, although Go sucks, it sucks less than any other language for the sorts of problems I use it for.
> And to be honest, this whole argument about pitchforks seems like a straw man
If you don't notice that criticism of Go is immediately and vigorously argued against... Well, you can't be following the comments very closely.
Huh? Have you ever argued against anything on the internet and not been countered immediately? Do you think if I'd publish criticism like this about, say, emacs, haskell, firefox, twitter or puppies, I wouldn't get comments immediately telling me that I am wrong and fundamentally misunderstanding what an editor, programming language, browser, social networking platform or adorable animal photo is all about?
I love Go. I know it's an imperfect language and because of that I do often hate specific Go idioms. So I definitely don't have a "bunker mentality" when it comes to Go; nor any other language. But in terms of "getting stuff done" Go has generally served me - personally - better than any other language. I just get a little sick of hearing about how Go is a "bad language" when what people actually mean is "it's not productive for them personally."
I can program in over a dozen languages, so I do have extensive experience outside of Go. And as someone who is language agnostic it never ceases to amuse and irritate me just how zealous people get when trying to prove personal preference as scientific fact.
The most popular languages are generally accidents of history. Unix gave us C, browsers gave us JavaScript, and Databases gave us SQL, etc.
This is the problem though - I think many people expect there to be a "one language to rule them all". Personally I like having lots of different languages that excel at some problems even if that means they fall short at other problems. But I think some people either want to specialise in a specific language, or spend so much time looking for perfection that they miss subtle beauties amongst a forest of flaws.
Edit: Thanks for proving my point everyone.
Edit2: To be slightly less snarky, despite the article I don't see any reason why Go couldn't be a fit for e.g. an oscilloscope which today is running a complete, often multi-core, linux system with 100k+ lines of code (with help from an ADC and FPGA etc. of course). If it wasn't for the fact that few people would undertake such an effort when that would be akin to swimming upstream against the ecosystem.
In short, these are entirely anecdotal and subjective points of view, so after the 1000th person says, "you are stupid, generics are amazing because .... my anecdotes" well eventually you tune it out.
Last, there are a ton of languages out there that have generics, richer type systems, etc. Go is trying something different, and given the lack of real empirical data, lots of experimentation is the best thing. Let Go do it's thing, and let the other language do theirs, why demand that all languages need to make the same trade-off on these topics?
Experimentation is definitely the right way to go (har!), but that doesn't imply that people should be mum about the results of their personal experiments! Obviously of these are actual scientific experiments, but when people (like the author of the OP) say "I've used Go and here is what I think", they are in essence reporting the findings of an "experiment" with the language.
I don't think anybody is demanding that Go make the same trade-off as other languages, they're just documenting their thoughts on the affect of the various trade-offs.
The thing is, a million developers can use a generic library, but only one has to develop it.
Excuse me now, I'm going to tune out a million boring arguments of the form "higher level languages are amazing ..." and go back to debugging IBM 360 assembly language program.
Nobody can objectively argue that these aren't useful, or that they could have been implemented in a non-generic way without destroying the language. Wouldn't the utility transfer to the developer's own code?
As for "let Go do its thing", I would argue that it already has been done: Plenty of pre-existing languages don't have generics. The lack is always felt, including in Go's direct precursors (such as Modula-2 and Oberon, languages that people later hacked generics onto because their real-world ergonomy as designed by Wirth wasn't great).
You can say that about any language. The people that like the language will always defend it. e.g. PHP, C, Ruby. They all have flaws and yet when one talks about their shortcomings, the people get defensive.
If someone started developing a language today and came up with C or PHP they would be criticized for many of the pitfalls of the mentioned languages and there would be a lot of improvements that could make those languages objectively better. But they are what they are because their design decisions were made under totally different environment than today and the advantage of using them is that you get to leverage everything built since then (well this argument is much stronger for C than PHP because PHP has alternatives that could be viewed as strictly better).
But Go is a new language. It's trying to sell itself as a better solution to existing problems so the level of criticism is going to be (justifiably) much higher - it doesn't just need to meet minimum usability bar - it needs to be better than existing defaults, and significantly so to justify the cost of switching - both in terms of learning and porting.
thats more the developers than the langauge. I'm a diehard ruby guy, but when people talk about its shortcomings or the benefits of another language, i listen. It only clarifies what can and cannot be done, and what would be better done another way or in another language.
I think its part the developer, part the community around it.
IRC, /r/haskell, whatever.
C programmers can be defensive when it comes to changes in the core language, but they're very receptive of all kinds of third-party libraries, you don't see much of "if you want <feature X>, you're doing it wrong". Take, for example, object-oriented programming. If you try to confront a seasoned C programmer about how C sucks because it doesn't support OOP, instead of being told that OOP is bad and C shouldn't ever support it, you'll most likely get a response saying that C does support OOP with the proper libraries, such as GObject, and pointing out that large C projects like the Linux kernel are already object-oriented.
Go, on the other hand, just pooh-poohes the concept. Clojure has a similar negative attitude. For example, the Clojure community is notoriously hostile to any suggestion of implementing Common Lisp's loop macro. There's no, "well, that's the beauty of Lisp, you can always write your own macros if you don't like what comes with it". Instead, you just get vitriolic condemnation of the whole idea of such a construct. If you write your own loop macro and post it in a Clojure community, the response is typically "why would you even think of writing such an abomination, what is wrong with you?", which is a disgustingly hostile way to treat people who are volunteering their time to contribute to the community.
I've heard people talking about it in Dart, Angular, and V8/Chrome, and I'm not sure if it's true or not.
In some cases, rigid type-safety is necessary, but I have trouble taking this criticism seriously while languages like Python enjoy extreme success. If Python can be insanely useful (and acceptably safe), then why not Go?
tl;dr: Go is not -- from a practical point of view -- a static language. (Note to pedants: I'm talking about Go's use, not it's formal nature).
Better tl;dr: Think "Python's type annotations" rather than "Rust".
To me, it's a replacement for Java, not C++. I think that's a reasonable target.
Mandatory GC, lack of generics and therefore rampant use of downcasting & duck typing -- these make it difficult to write safe and fast code for systems level or embedded type work.
Why must a systems programming language be static and strongly typed?
I don't mean to be flippant, but to me, 'systems programming language' means 'a language that facilitates productivity for systems programmers'. By that description, Go certainly qualifies.
>Mandatory GC, lack of generics and therefore rampant use of downcasting & duck typing -- these make it difficult to write safe and fast code for systems level or embedded type work.
Point taken, but not all system's programming requires such extreme safety.
The requirement most people mean, when they say "Go isn't a systems programming language", is the ability to acurately control execution. With Go, you can't, because of GC.
Google's definition seems to be "building large systems". For the types of large systems Google wants to build, Go works very well.
But others define it as "building operating systems". Go is horrible for that because of garbage collection and inability to directly access the hardware.
>>> The Go programming language is an open source project to make programmers more productive.
Go is expressive, concise, clean, and efficient. Its concurrency mechanisms make it easy to write programs that get the most out of multicore and networked machines, while its novel type system enables flexible and modular program construction. Go compiles quickly to machine code yet has the convenience of garbage collection and the power of run-time reflection. It's a fast, statically typed, compiled language that feels like a dynamically typed, interpreted language. <<<
But more realistically, it makes it easier. Those things still manage to be hard at some point.
"concise"
"novel type system"
"flexible type system"
Just a few things that need correcting. Really ... "novel type system" ...
C doesn't have a mandatory runtime, ubiquitous dynamic dispatch or a GC, and it lets developers decide whether to stack or heap allocate.
cmrdporcupine also isn't talking about generics, they're replying to the assertion that
> Go is not -- from a practical point of view -- a static language
I mean I am no Java expert, but e.g Android Studio is miles ahead anything the go team will be able to ship in the next few years. And I don't think they're even focusing on building such tools since they seem to be stuck on building a debugger right now.
I wouldn't even say Go's target market is Java. I'd say it's actually Python. Rob Pike has spoken about this [1].
I like Python. It's fun but for anything nontrivial I've become disillusioned with it because the supposed productivity gains are offset by having to write unit tests for spelling mistakes and typos. So I like Go for this purpose. It's not quite as expressive as Python but it's in a sweet spot IMHO.
[1]: http://commandcenter.blogspot.com/2012/06/less-is-exponentia...
I'd love support for "check this project" that would essentially be similar to compiling a Go project.
Python is awesome for so many things: - Quick project iteration - Web development - Testing (test suite is actually pretty sweet!) - General purpose programming and scripting
Currently, not the most productive tool for large projects or complex projects, or projects where static analysis pays huge dividends (usually this fits in one of the previous two categories anyway).
Doesn't mean it has to be: but it'd be really nice to have...
What's incredibly infuriating to see a language that clearly has everything it needs to offer generics - indeed it clearly has a generics implementation already written, since the builtin types are generic - but it won't let me use them.
For those who are still arguing about what Go replaces (C? Java? Python?), I try to look at it practically. In the interest of productivity, I might want a language with garbage collection. Ok, so let's set C aside. In the interest of performance, I might want a compiled language. Ok, so let's set Python aside. And maybe I don't care a great deal about portability, so set JVM languages aside.
Go feels like a very practical language, and that's because it is a practical choice for a lot of people.
I hope the Go community does a better job of embracing feedback and caring about language design. It's young enough that breaking improvements could help in the long-term, even if they hurt in the short-term.
No piece of feedback is ignored, I'm not sure how you've gotten that idea.
Give Go some time. It's inflexibility will inevitably yield some interesting baggage of its own.
BUT, it must also have a nice set of high level abstractions. For web and application level stuff rather than system level stuff.
So, what's that magic language? Really!
Go is almost that language, but it "missed it by that much."
The language itself was frustrating to me in many of the ways outlined in the article.
The community was similarly frustrating.
One anecdote that really stuck with me was when enquiring about explicit language support for the error handling pattern. E.g.:
f, err := os.Open("foo.bar")
if err != nil {
log.Fatal(err)
}
It is something you perform extremely frequently, and it takes up an incredible number of lines of code. The response from the Go team was (paraphrased) "We don't see the value in making this pattern more terse when you can just write a macro for your editor to automate it".The problem with Go is that is very idiomatic. If you want to work with Go you need to learn its way, and somehow you need to accept the trade-offs behind its design.
If you do not see any advantages in any way, probably it's not the right tool for you, and that's ok. No problem at all.
Much easier to understand what is going on, no need to find out if something in the call graph of the method I call throws or not. Also error handling code is where the error occurs, not some completely different place.
Properly handled exceptions aren't any less code anyways. Unless you can just drop everything on the floor.
1. Expect you call to os.Open to not fail 2. Then do stuff with it 2bis. Or the running process will crash, the error logged, bad state won't mess up the flow and a dev can always hot-patch it
Go seemed to be borne primarily out of an ops-driven ethos. The fact that it's sort of stupidly become the current darling language of Silicon Valley hipsterdom isn't really Go's fault.
Then you weren't really listening, tbh. Everyone on the go team has acknowledged the usefulness of generics now. It's just that so far no good solution for the associated tradeoffs has presented itself.
Thats not limited to the Go community. It seems to be an attitude that is sweeping the second(?) generation of FOSS developers.
Seems like just working on code is not enough any more, it has to have some kind of social/fixing-the-world angle.
It makes me feel very old. I just want to keep my head down and hack.
I keep my head down, and hack. I don't care about those circuits. And as a result, I'm not as visible.
Of course there are the superstars that you hear about, who are super active, writing new languages and libraries and whatnot, but I would say that is the extreme end of the bell curve.
Politics isn't a dirty word, it's just the reality of having more than one person on the planet.
This is true. And what's always been funny to me, is the predecessor language(s) for many Go programmers, such as Python, had people saying similar things about how you don't really need static types, we know best. Then suddenly they saw the light.
All of which is to say, I've noticed that many people who enjoy Go come from languages which Go is a step up from rather than a step down. And that's good for them, but compared to what else is out there, it is a step down.
Every so often people start grumbling about C. They call it a terrible language because the specification contains undefined behavior (and less frequently because they removed the linter from the compiler early on). These arguments are well known and have been addressed over several decades. Any complaint about undefined behavior has to account for the fact that said omissions are intentional and have been well-argued for by the ANSI committee and community of C compiler developers. If you can't do that then you're complaints are just going to fall on deaf ears: you haven't contributed anything that we don't already know.
If anyone wants to introduce generics into Go they're going to have one hell of a debate on their hands. I believe the reasons against it are firmly established and it will never happen. I may be wrong but any argument for their inclusion has a lot of work to do.
This doesn't make Go a bad language. It's probably just not the right fit for your purposes if you really need generics. Such abstractions are not a universal property of languages. I get by fine in C without them... but I prefer C (or Common Lisp) because if I did want them there are good libraries to give me those features.
I don't know when it became fashionable to have such opinionated languages but I tend to disagree with most of them so I just avoid them for the most part.
Implementing goroutines and channels requires language and runtime support for green threads that are n:m multiplexed on top of native threads. It can not be implemented as a library in most languages, at least not efficiently. Any language with thread support can set up threads and put a concurrent queue between them, but that's hardly the same thing.
Languages such as Go, Erlang and Haskell do this. Interestingly, early versions of Rust had green threads (iirc) but later migrated to using native threads only.
[0]: http://libmill.org/
Even JS can be used to implement such concepts via the use of generators[1].
Maybe things have changed since 2013, but I feel like this is a fundamental limitation of running on the JVM vs what Go can provide in its runtime.
Edit: Also, it appears to be much easier to simply "run out" of Clojure coroutines than Go goroutines, but perhaps that's also changed. Anyways, my point is that by core.async operating as a macro you still can't overcome limitations of the underlying runtime, whereas Go's runtime was purposely-built to support goroutines.
https://github.com/clojure/core.async/blob/master/src/main/c...
That's not something that could be done with golang as far as I know.
With the added convenience that shared mutability is pretty much nonexistent.
Anyway, there's a reason the phrase "tacked-on" has such negative connotations.
Erlang at least is consistent on this -- it has that hammer well tuned and isn't afraid to pound nails with it.
But OTP isn't really possible either because Go lacks links and monitors.
Plus not being asynchronous and no distribution (wouldn't want to go over the network with sync channels anyway)...
From a personal standpoint, it's missing a lot of the features I like, namely ADTs, list comprehensions, folds, maps, etc. But that's just my personal style, not something wrong with Go. Go programs don't necessarily always look pretty but you can usually understand them after a minimal amount of study because the language is so simple.
Yes, CSP[0] is a very interesting concept. But it's not something unique to the go language.
[0] https://en.wikipedia.org/wiki/Communicating_sequential_proce...
Except when it is not. Message passing style of concurrency is just a dual of the classical blocking concurrency with critical sections, mutexes, monitors and conditional variables. An actor is a dual of a critical section. Actor's mailbox is a dual of a mutex. Sending/receiving messages is a dual of wait/notify. With any complex CSP program you can have all the same problems: race conditions, starvation, deadlocks (livelocks) etc.
Queues ("channels") are a good way to limit complexity of threaded code by treating each process as an agent. Besides some syntactical sugar Go doesn't really support this better than most other languages with threading, like Java.
Go has a weird thing going on where channels are sometimes used as a kind-of-replacement for iterators, which is error-prone since the "obvious" way to do it doesn't allow the consumer to stop the generator without a side channel. This can lead to buggy code that leaks goroutines, since goroutines can not be garbage collected.
One of the best ways to reduce the complexity of threaded code is immutability - preventing race conditions by making sure a structure never changes while being read. Curiously, Go has no way to mark an object as immutable, and does nothing to detect or prevent objects being unsafely accessed from different threads.
The magic of channels comes with select{}. Considering them to be only threadsafe queues is really missing out.
Supporting select{} in other languages is possible, but difficult and rare.
Zero length channels are a key part of coordinating concurrent threads in Go.
That's by design. Rob Pike fostered that "we know best" opinionated style in the community from the very first Go announcements and tutorials. I encourage you to read the design documents if you haven't: they throw light on the majority of decisions behind the language.
It's not really for me, but I understand and generally respect where they're coming from.
----
> If you want to know how to handle some new layout situation, run gofmt; if the answer doesn't seem right, fix the program (or file a bug), don't work around it.
http://web.archive.org/web/20091113154825/http://golang.org/...
> If it bothers you that Go is missing feature X, please forgive us and investigate the features that Go does have. You might find that they compensate in interesting ways for the lack of X.
> More directly, the program gofmt is a pretty-printer whose purpose is to enforce layout rules; it replaces the usual compendium of do's and don'ts that allows interpretation.
> Go doesn't provide assertions. They are undeniably convenient, but our experience has been that programmers use them as a crutch to avoid thinking about proper error handling and reporting
http://web.archive.org/web/20091114043443/http://golang.org/...
> Orthogonality makes it easier to understand what happens when things combine.
> By their very nature, exceptions span functions and perhaps even goroutines; they have wide-ranging implications. ... It would be nice to find a design that allows them to be truly exceptional without encouraging common errors to turn into special control flow that requires every programmer to compensate.
> Generics may well be added at some point. We don't feel an urgency for them, although we understand some programmers do. ... This remains an open issue.
> Experience with other languages told us that having a variety of methods with the same name but different signatures was occasionally useful but that it could also be confusing and fragile in practice. Matching only by name and requiring consistency in the types was a major simplifying decision in Go's type system.
> The convenience of automatic conversion between numeric types in C is outweighed by the confusion it causes. When is an expression unsigned? How big is the value? Does it overflow? Is the result portable, independent of the machine on which it executes?
http://web.archive.org/web/20091113154906/http://golang.org/...
> It is better to forgo convenience for safety and dependability
http://commandcenter.blogspot.mx/2012/06/less-is-exponential...
reading many of the points here makes me think: alienated java user who doesn't like change
We all know Rob Pike is smart. Doesn't mean I have to agree with him. I don't like the things that Go is conservative about. I think the lack of a good way of doing clear type safe operations in a statically typed language is a terrible oversight.
Someone citing Haskell or Rust is probably the exact opposite of the stereotypical "Java drone," line-programmer churning away on bad features in the same fossilized Spring app for 10 years.
And this encapsulates perfectly why I don't like Go. Writing Go feels like putting a straightjacket on myself. It seriously feels uncomfortable, which says a lot considering I come from a Python background, and I'm used to a language that tries to enforce a particular philosophy. In a lot of ways, Python's "there should be one and only one obvious way to do it" feels like working with pre-established harmony, while Go just tries to force its own arbitrary discipline on me.
If I'm going to use an AOT language, I'd honestly rather have the flexibility offered by D or Nim. And if I don't have to use an AOT language for something -- and Go is mostly being marketed as an alternative to non-AOT languages like Python and Java despite being AOT itself -- then I'd add Python and Perl 6 as languages I'd rather work with than Go.
Thought experiment: write a proposal that works through adding algebraic data types (or even just special-case the error handling as option types, if that is easier) to Go. I've tried it; I found that doing so brings up a bunch of other problems that don't make it an obvious solution. (E.g. you'll want a "match" operator. And then that means you need all statements work as expressions. And you'll have to change how zero values work, which are pervasive throughout the language.) And I really like algebraic data types in Haskell.
At some point if you really want Haskell you should just use Haskell. Or Rust. And then you will find out that those languages have problems too, and you will understand that engineering is a question of tradeoffs, not of feature checklists like this blog post.
I tried a project in Go and really disliked it. For my personal projects, I will not start another one using it. But there are already situations where I have to write Go if I want to do my job. If I don't want that set of situations to grow I have to speak up.
You don't need to make everything an expression for pattern matching to work. See Bjarne's C++ proposal: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n344...
You might have to change zero values, although you could make algebraic data types all be nullable if you wanted to avoid doing that.
I agree that you can make pattern matching work without expressions. My intuition is rather that it's not especially useful, because you need some way to make use of the result of the match.
Either you embed the rest of the function into the branch of the match statement, or you're back to stuff like:
foo := ... # Some zero value ...perhaps nil?
match get_foo() {
Some(x) => foo = x
None => return
}
# now use foo here
That is, to make use of the result of the pattern match you need a way to get the value out of the pattern match which puts you back in the kind of code where there's no pattern match. You could make just "match" be an expression but now the arms of your match must be expressions which runs again into the problem of Go being a statement-oriented language -- for example, you might want to construct a struct in your match arm but if you can't fit the struct construction into a single expression you're stuck again. (It's a similar problem to Python's lambda.)There might be some other nice way to make this work, of course! All I am suggesting that if one does the effort of making a concrete proposal you'll find that any small feature like this brings in a bunch of related ideas (like Rust's semicolon) and is not as simple as "just add option types".
To me, that just sounds like the designers really painted themselves into a corner. I have yet to run into a situation where everything-is-an-expression feels like a problem. Am I missing something?
> At some point if you really want Haskell you should just use Haskell. Or Rust. And then you will find out that those languages have problems too, and you will understand that engineering is a question of tradeoffs, not of feature checklists like this blog post.
I think it's clear that Go has contributed to the conversation. In really accessible ways, it made some powerful points on the benefits of auto-formatting, fast compilation, static binaries, and so forth. But there's just so much missing of the highly productive points made by other languages, and there seems to be so little energy in the community to progress on those points. In that sense, it feels to me like Go is a bit of a dead end.
It manages to be pretty FP-friendly without being FP-front-and-center and keeping intreoperability with Java as easy as possible, and staying pretty simple.
But yes, you need to rethink the design from the start. I wish it would have been done differently, less C-like, but it hadn't.
I suppose once that language comes along we can stop our constant whining ;-)
Very much working as intended, I believe. Experience from languages that support those features has shown that what we gain in the very few situations where those extensions make sense (such as defining mathematical operations on vectors using the same symbols that are used in vector mathematics), we lose in too many developers thinking they have a clever shortcut that an existing operator would be perfect for, to the detriment of readability and comprehensibility.
This is also the era of code-analysis-by-search-engine, and operator overloading harms that feature significantly. If I need to find all instances of vector addition in my code and I'm searching for '+', I'm going to have a bad time.
boostfs::path path("/some/path");
path /= "yourfile.txt";
Meanwhile, reading your code without being familiar with boostfs::path, my brain grinds to a halt while I try to understand what in the hell dividing by a string is supposed to do.This is one of those "well intentioned" features that turns into a quagmire in practice.
Except when not having it is the worst. Working with BigDecimal in Java is hell because it does not have operative overloading, meaning while you avoid
boostfs::path path("/some/path");
path /= "yourfile.txt";
you get saddled with bullshit like x.add(x.add(ONE).pow(2).subtract(x)) x.add(x.add(ONE).pow(2).subtract(x))
Especially because sometimes it is difficult to decide whether you should have x.foo(y) or y.foo(x). However, add(x, sub(pow(add(x, ONE), 2), x))
Is perfectly acceptable in my opinion (add some indentation if it's difficult to read). As long as you can pass parameters and return values without tricks (ie. passing pointers), this is quite nice. You should even be able to do this in Java with "import static". Or C++ with function overloading.I'm definitely not a fan of C++ -style operator overloading, where you only have a finite amount of operators with set precedence/associativity and then they get overloaded to meanings that the symbols don't convey. On the other hand, I'm not sure what to think of Haskell either (where you can define arbitrary operators, like >>=, <+> or <$>). It's not as limited as C++, but there are some quite nasty examples that have gone overboard with operators.
Overall, it seems like operator overloading adds a lot of complexity to a language but the benefit is arguable.
On the contrary, when all you have is a couple of examples that aren't even that bad and a slippery slope argument, you are on very thin ground, rhetorically speaking.
path += '/' + 'yourfile.txt';
It's also entirely possible that I'd already subconsciously read ahead and so knew that it couldn't have possibly been division.Nope, this is just incorrect. The C++ is completely dominant in large swaths of the software industry largely because operator overloading allows the writing of generic algorithms (which allows you to write large scale software without losing C-like performance). Without operator overloading, it is much harder to write a function that can be specialized on types that weren't specifically designed for such use.
In Python, Numpy, the Decimal class, I could really give examples for days of cases where operator overloading is essential. Go doesn't have it, Go doesn't have a lot of things, and Go will always be an also-ran language that isn't adopted outside of a very narrow domain.
The fact that built in types are 'special' and only they can support operators such as [] is enough for me to avoid the language. The complete lack of generic programming is more than enough.
Compare (fake Go-with-Swift-generics syntax):
func Distance<N>(x N, y N) N where N Number {
return x.Mul(x).Add(y.Mul(y)).Sqrt()
}
Versus: func Distance<N>(x N, y N) N where N Number {
return Sqrt(x * x + y * y)
}
If your reaction is "well, Distance doesn't look too bad like that", I can replace it with matrix multiplication or point-inside-triangle testing. Not having overloading quickly fails to scale.Type 2 defines: .plus(x)
Type 3 defines: .vector_add(x)
Now, implement a function 'average' that can work on any of these three types.
If you can get everyone in the world to agree to a convention of how to express 'addition', then there is no difference, except we already have a convention for 500 years, and it is the '+' operator. Why you think the '+' operator is confusing but .plus() is not, that is what confuses me.
Or how about 'minimum'. In C people end up writing a minimum C macro, because there's not even a way to write one function that works on int, long, float! What a sad world that is, where you have to meta program to implement min(x,y).
This is true of methods too. If you're searching for vector addition and you grep for "Add()", you're also going to have a bad time. To have a reliable code indexing scheme, you need typechecking/name resolution information, and once you have that you can easily handle operator overloading as well.
This is likely a short-term reality, but it's the current reality.
However "working as intended" I think is also the response of Go to their lack-of-generics, which I think is kind of crap.
This is what Java designers thought as well. See where this has led them.
The response I've overwhelmingly observed from qualified voices isn't "boo generics!" but "generics are terribly difficult to get right, and we want to know more about Go's niche before making any design decisions in that realm".
I suspect you're reading a lot of drivel from web programmers who discovered net/http last Thursday. It's hard not to be frustrated with the internet, I concede...
Where the hell did you get that from?
So I think operator overloading can be exploited pretty horribly but can also make code far more intuitive. It's certainly not something that can't be worked around but I always err on the side of letting it happen and the community can direct people to using them most properly.
A difference is that operators tend to have semantic baggage, which can be a huge boon when using operator overloading for e.g. calculations. C++ has demonstrated that it was a very bad idea to overload operator against their semantic baggage, but the lesson to draw from it is "don't do that" not "operator overloading is the devil".
Go has specifically rejected the complexity that these features introduce, both in the implementation of the language and the writing of programs in it. If you want those features, just use a language that has them. Some other people might not care about those features, and prefer the simplicity of Go, and that's fine too.
Things that are 'good' for me: Good concurrency primitives, single binary deployment with no dependencies, a language that can be picked up in a matter of days and a consistent coding style (gofmt).
If another language suits you better than use it, but to call Go "a regression from other modern programming languages" ignores the many reasons developers are using it.
I applaud your advocacy. Using other languages is pretty much my personal plan.
The problem, though, is that like everybody else in the industry, I don't work in a vacuum. Other people may be making platform decisions for projects I work on.
Complaining about Go's limits seems like a good additional strategy to minimize the chance that I'll have to work around them again in the future.
It may not choose entirely randomly, but that doesn't mean that it chooses reasonably. You mentioned OOP everywhere -- a philosophy that's driven several dominantly popular languages and has been seen as a mark of professionalism. If the industry is any guide, Go's break from the norm here already calls that decision into question.
(I happen to think this is one of several areas in which the industry is wrong, but then again I don't see the industry at large as particularly rational.)
> We do really need complexity?
No software developer wants complexity, every software developer is trying to manage and limit it to the extent of their resources.
The question is whether language simplicity leads to software simplicity.
It seems apparent Go's designers believe this is the case, and have offered a simple-ish language on a feature diet that avoids much in terms of type expressivity or facilities for abstraction that rise to the level of augmenting the language itself.
I think this can work for some problem domains, particularly one that is closely-fitted to built in types and libraries. But once your problem domain isn't close to native language facilities any more, you're forced to write more and more code to get around the limits of the language's expressivity. That ends up being more machinery and surface area to keep track of interactions between... which, in my experience, is where complexity creeps in rather than having to understand language features.
Needs change with time. In the current context, if Go is an improvement in some tech areas I think it will get some degree of success. Otherwise I think will decline after the first hype.
By the way, I agree with you about writing more code to overcome language limits. The hope here is that using idiomatic Go you will end up, no matter what, with a reasonably understandable code base, even for libraries and tools. It's a goal, I don't know if reachable or not.
That's not a very good attitude. Some people have to use Go (for work), so it doesn't make sense to just ignore them. If every language had the attitude "It's fine as it is, stop complaining", then languages would never improve!
The one thing that seems to be missing from these discussions is that Go fits in an unexpected niche. I come from a web development background. I grew up on Perl, ASP, PHP, and Javascript. I dabbled a bit in C in college, but I always felt like I was fighting to avoid shooting myself in the foot with it. For me, Go was a huge step up, with an extremely friendly and approachable syntax, comprehensive standard library, and great toolsets.
On the flip side, we've got a bunch of C/C++/Java developers who would rather compare it to what they've been using for decades. I've no doubt it's missing a slew of very important features from that perspective. Go does seem to be capable of many of the same things as those languages, so those criticisms are likely valid, but for those of us that aren't trying to use it as a low-level systems language it's still pretty great.
Go could probably be improved in a lot of ways, but at the moment it serves my needs really well. For me, Go is good.
You could start by checking out https://kotlinlang.org/ - it targets the JVM so the tools are much better than what Go has and the library ecosystem is much larger. The language is a straightforward imperative style language that will remind you of Go. It also will take just a few days to learn, at most. But it has a slew of features Go does not have which have been proven in many of the world's biggest and most popular languages.
That's not to say those other languages don't interest me, or that I would eschew learning for the sake of learning. I've been eyeballing Rust for a while, and I do think it may someday fill the role Go currently fills for me, but for the type of coding I currently do Go is more than sufficient.
People like JVMs because they provide a lot of services that are really useful, such as:
• State of the art garbage collectors, which you can tune for throughput or low pause times (there's a fundamental tradeoff here, there's no one-size-fits-all GC algorithm)
• Visual debugging that always works, including remotely
• Stack traces that always works
• Advanced profiler and monitoring tools
• Very robust and portable build systems
• Extremely fast compiles (this is touted as an advantage of Go, but I never find myself waiting for a compiler when working with Java or Kotlin).
• Giant standard library and even larger ecosystem of well designed and documented libraries to do many different tasks
• Language interop - you can normally use libraries written in one JVM language from others. This obviously helps with the former point.
• In some cases (e.g. actor frameworks and big web servers) code hotswapping and dynamic loading.
The Go runtime lacks a good chunk of these useful features: the last time I worked with a Go shop they told me debugging hardly worked, because error handling was "propagate an error code" they never had stack traces in their logs for failures, profiling was primitive or not available at all depending on platform, the standard library was small (compared to the JDK), and language interop was "it can call C". Also the GC sucked, though I heard they have a better one now. But it's still a one-size-fits-all approach, which has well known problems.
Me too, and that's precisely why I kept complaining for a time about these exact stuff until I moved on to something else.
People don't complain about the stuff they do not use, they actually complain about the stuff they have/want to use everyday. But that's a good thing for the remaining users on go-nuts, most people that complained moved on, which means that a good chunk of them stopped using Go. I really really wanted to use that language, the "you don't need that in Go" patronizing tone on the mailing list made not want to use it anymore.
I don't want to start an imperative-vs-functional war or anything, but I've noticed many of the people complaining about Go seem to be functional programming aficionados. Is this because of how much they like embedding and abstractions, or is it because they're trying to put the square Go peg into the round FP hole?
But is that unreadability due to the nature of generic code, or due to the empty interface hack that Go forces you to use?
Now that structures based on Category Theory (generic types, lambdas, monads, futures/promises...) are being adopted by most mainstream programming languages, side effects can be described in a declarative way that is thread-safe and thus amenable to parallelism, will still allowing developers to write in a mostly imperative style.
It's a rare instance where we can really get the best of both worlds. I'm optimist about future developments of PLs.
> If I write a function to sum a list of numbers, it would be nice if I could use it on lists of floats, lists of ints, and lists of anything else that can be summed.
I agree with the author and continue reading, expecting to see an implementation of that function in each language. I keep reading and re-reading to try to figure out how the first two code samples (Rust and Haskell) are summing a list. I feel like an idiot, because I can't figure out how that code is possibly summing a list. Thankfully, the next paragraph explains it, but a heads up would have made it more clear.
The article continues with pairs of Rust and Haskell -- as a reader, I'm thinking, "Yes, yes, but show me how this compares to Go." Finally, when I get to `Go's Solution: interface{}` I feel like I'll be able to compare the languages... but instead of implementing an already-mentioned problem, a new problem is introduced:
> Let's say you wanted to write a function that printed a hash code for objects that could be hashed.
As a reader, I have too many things in my head now.
I think the author probably has valid points to make, and I will now finish reading the article. Hopefully some of this feedback is helpful (I'm not trying to be a jerk).
I did that in an effort to be fair to Go. You can write a generic Hashable interface in Go, so I started with that. The very next example is why you can't make a generic sum over a list in Go. I didn't want people to get the idea that Go didn't support any sort of genericism at all.
Personally I don't want to go pick through half-baked third-party packages, mix and match concurrency models or GC. I have experienced enough of that in Node and it's not pretty. Having it all consistently implemented in the stdlib is a great feature.
Go not being cute was also something I found attractive, I'm not particularly worried about how much I type, because typing has never been a bottleneck. I prefer that code is easy to comprehend. My biggest problem with Go as a language is the arbitrary nature of some aspects when it comes to assignability etc.
When Rust or Haskell can say the same I'll definitely invest in them but until then it's just not a problem. I don't think it's about one language being academically better than the other, it's what is best right now for the job you're doing. I want those languages to do well of course, more options the better, but for now Go ticks the right boxes for a lot of people.
He never said Go was the only language which had a wonderful standard library, only that it's
> one of Go's biggest strengths
Just looking at the Option<> type in Rust alone makes you wonder just how many places have you really forgotten to check or write tests to verify you check for nil values. Probably too many. That one thing is enough of a win over most languages today that I'm sold on the concept entirely.
Can we all agree to raise our pitchforks and torches in the general direction of the terribleness that is null?
And how would someone implement Option<> if not for type generics. Because of the lack of type generics in Go your stuck writting run time tests for things like type conversions and nil value checks. A complete waste of precious developer time. Thats the real loss. Time.
I don't want to say the word "perfect language", but there is no such language that can meet the demands of every nerd on the planet, the goal of the Go programming language is stated clearly, compiling speed overweight the needs for generics, that's why LLVM is not considered for the go compiler.
Also the language is considered feature complete, if one doesn't want to met with "angry pitchforks", do the homework, e.g. the generics topic has been picked up over and over, that it's not funny anymore, if you are interested, the amount of debate online can take days to read.
Will Yager's blog seems to have no possible way of determining when a post was written. Which is especially frustrating since the very first paragraph of the post in question includes the phrase "at the time of writing". Well, when was that!?
Looks like I wrote it in June 2014. Someone posted it here after I asked for feedback on /r/rust, so it's been almost a year and a half! It pops up every once in a while :)
There should be a point where a problem has been talked about ad-nauseum. I think people saying this will fall on deaf ears misunderstand that the Go community has been there, done that. We all know it, we'd like to have it and the Go team knows about that, and they stated why it's not there yet (because the tradeoffs available to them aren't interesting enough to make a decision with either implementation).
Until this changes, I think we can all just get over it.
The problem is that most big languages today are hammers, and they can are used to hit all sorts of nails to fasten all sorts of unholy planks together. Go is a screwdriver. Still good for construction, but you need to be using it in the correct way and you can't wail away at the problem the same way you're used to. Hammer people try to pound the screw in and get frustrated at the resistance they encounter. Perhaps they should instead ask themselves why the choices have been made, what possible benefits come from using a different tool. And you know what, maybe they just prefer hammers. Nothing wrong with that.
This is the standard Go defense. 'It's not Go, it's you.'
I have written some larger projects in Go, and I am in full agreement with the article - Go is a relatively weak and repetitive language, similar to pre-generics Java.
So, why does Go gain so much traction? While it may be a weak programming language, this is often compensated by excellent tooling and easy deployability. Plus dyed-in-the-wool Unix users (me inclusive) never liked the JVM baggage that comes with JVM languages.
I like other languages like Haskell (haven't looked at Rust), but I can't use it on the projects for a variety of reasons.
If you didn't do any Java for 10 years then maybe Go looks good in comparison, but I don't see how with the modern stuff, especially when you compare IDEs, debuggers, profilers and other tools.
But if you want something much more concise than Java, look at Kotlin or Scala.
I've also worked on Docker, which while the design patterns are interesting, is a larger project that works very well with Go!
How do we know this? Has anyone written enough Go in an environment with a lot of engineers to make that determination?
This is the argument that's always thrown out. The OP obviously understands the language very well. Saying someone just "doesn't understand" belittles those that are voicing genuine criticisms. A language shouldn't be based solely around ideology.
I don't want to get too philosophical, but aren't all languages ideological to some degree? Certainly somebody who always chooses to write Clojure over Java has some strong beliefs about how code should be structured and behave. Go's is just another philosophy borne out of frustrations with "features" of other langs.
* Its forced syntax stops syntax wars. * Compiling down to one binary makes deployment easy. * Its has concurrency out of the box. * Its insanely fast. * A strong community to hire developers easily enough.
Does Haskel/Rust have the same criteria? Shurgs
- There are curly braces available if you really want them, but people almost always use the whitespace-dependent syntax. There are usually a few ways you can organize your code, but I have never seen any "syntax wars" over Haskell code.
- Haskell compiles down to one binary. Foreign C libraries are linked dynamically by default, if that's being counted.
- Comes with (very cheap) green threads and threading primitives, along with useful concurrency structures (like channels). The standard library includes STM for safer shared mutable memory, and many libraries (like async) are available that extend this. I have not done much Go, but I think forkIO is basically equivalent to "go".
- I couldn't find a whole lot comparing Haskell and Go in particular, but here is one blog post where Haskell was about the same speed as Go, in one narrow application: https://togototo.wordpress.com/2013/07/23/benchmarking-level.... The http server (Warp) used by some web frameworks (Yesod, Scotty, ...) has been noted to be very performant.
- Haskell has a strong, active community. It's not super big, but it seems to me the number of open haskell jobs is smaller than the number of qualified, talented haskell users. Recently there was an issue with a company advertising a non-Haskell job on the haskell-cafe mailing list, because they believed they could get some good developers that way.
EDIT: I posted this without realizing I loaded this page yesterday, and that there were already some responses
Okay, but so does any in-company linter.
> * Compiling down to one binary makes deployment easy.
Rust and Haskell are both compiled to a single binary, typically, and both can be statically linked (with some work.. this is getting better)
> * Its has concurrency out of the box.
Rust is actually a systems language and does not have a decent semblance of concurrency (beyond OS threads, which it does very well) because it is very difficult to actually introduce/keep consistent at that level. (AKA: Why green threads were removed)
Haskell has one of the most advanced runtime systems of any modern language, and it does support Go-esque concurrency/parallelism (along with every other concurrency style you might want - as libraries).
As a bonus: in Haskell, you don't typically need to worry about the dangers of multiple concurrent or parallel routines manipulating state in unsafe ways, etc. STM is pretty great, too.
> * A strong community to hire developers easily enough.
If you want a "Go developer" - there are plenty of them. If you want a strong generalist who can learn the technologies you are working with (be it Rust, Haskell, whatever), there are plenty of those, too.
Go does seem like it reduces developers of all skill levels to some common denominator, allowing easy termination/hiring. Whether or not this is a good thing is debatable.
> Rust is actually a systems language and does not have a
> decent semblance of concurrency
I have bias here, but so strongly disagree. Many concurrency errors are at compile time in Rust. Rust has a really, really strong concurrency story.Last I checked, there were no thread-safe async/await primitives, coroutines, standard event-loops/reactors built into the language or the stdlib, though I would be very happy if this turned out to the case.
To preempt: Mio is not an acceptable answer without multi-threaded reactor capabilities and compiler-supported primitives to make the callback interface pleasant.
I would also state that Mio makes me fear that Rust will suffer the same horrible fate as Python or Ruby in this department: tons of fragmented, incompatible implementations with no blessed one. I really want to use Rust, but this is a deal-breaker.
I and other team members were literally in a few hours of meetings over the last few days to talk about this, and how to ensure it won't happen. It will be fine.
1) really fast compilation speed
2) goroutines
3) gofmt
But I learned F# after learning Go, and it felt like I was walking out of Plato's cave. Its hard to use a Go-like language after using the ML-style features described in this post.
Most modern static languages shift the debugging from run-time to compile-time, which is a huge win in my opinion, but Go does not do this. You don't even need to go "pure functional" to get the benefits (as in Haskell), Rust/F#/OCaml are fine.
Trying Go had practically the opposite emotional response: It didn't take long to get a bad taste in my mouth while using the language (a lot of, where is feature X from my favorite language, and why does the Go approach feel so jagged by comparison?), and as I read blogs like this that emphasize the weaknesses of the language, I don't feel compelled to write anything using Go.
With so many options, why bother with Go? Am I missing something?
The Bad: Hard to keep DRY, writing testable code can require a bit more planning that one may be used to, frustrating newbie experience[1]
[1] go command errors if run after installing if you don't configure it (set proper env vars) first, tools that are basically essential to having a good experience with the language aren't packaged with it and have to be tracked down individually (probably someone's written a nice shell script that takes care of that, but it's silly that that was necessary)
Which is the article's point.
Rust is like a phone with a lot of buttons and commands, give you more options and freedom of choice. Go is like a simple phone with very few buttons which has enough to enable you the real purpose of the phone, to make phone calls.
Its just more pragmatic, and that doesnt make it a sin.
Particularly, i like to have options.. its good we have them all, and we can choose the right tool for the job.
I was excited about Ruby because of Rails; only after working with it did I pick up a book on Ruby itself and come to appreciate the cleverness of block arguments (Ruby's insight, that functions that accept another function as an argument almost always accept at most one, so special-casing the syntax for that to make it clear, was really quite clever). And then I migrated away from using Ruby when I started to care about execution speed and couldn't escape the feeling that I was investing more time keeping up with the framework changes than I was writing my program.
For Go, I can write fast web servers in it. That's what I want, and it shines for that use case. I haven't looked at Haskell for that use case yet. Rust is still figuring itself out in that space (http://arewewebyet.com/). Go, in contrast, has a very solid commitment to backwards compatibility until the major version number changes.
So my general take on Rust and Haskell, specifically, is "Wake me when it's cooked."
With similar argument, I could list every feature of xml, show that they are not easily solvable with json and conclude that json is not good.
Json became the defacto serialization format, but in my opinion, Json isn't good for everything. Json and all its tools around it keeps trying to be like XML.
For me main selling point of golang is small lightweight threads with event loop. You write sequential blocking code and you get concurrency built in.
I love both languages, both has their advantages, but Rust lost community while changing syntax and versions were not stable until v1.
Its not about total relativism, its about trade-offs.
> All well-written code is easy to read, and most poorly-written code is hard to read. Obviously Go can't change that.
I completely disagree. Languages with lots of features can make poorly-written code vastly more difficult to read.
In short, the author just points out features that Go could have but doesn't, which is not a good argument for saying that Go is "unconditionally" bad. All those missing features are missing on purpose, they are not bugs nor there is some kind of inherent defect in the language.
To me, the only two things that really bother me in Go are: 1) sometimes, the lack of generics, particularly when dealing with data structures and 2) the lack of a proper and official dependency manager. (The go tool has so many officially supported auxiliary tools, why not also a dep manager supporting versions etc.?)
It sounds like the author wants to turn Go into Java or Haskell. If that's what the author's preference is, then just use Java or Haskell. I don't even use Go, but to me this post is simply just whining, but the author doesn't appear to understand the fundamental reason of how or why Go was designed.
The creators of Go made opinionated decisions on how the language would behave. Generics weren't left out because of oversight or accident, that was a conscious decision. Everything in his list was a conscious decision. Go is one of the most opinionated languages out there, and it's definitely not flexible to do whatever everyone wants. If you don't like it, then use another language. It's pretty simple.
Go is already a Java. It's just that by and large it's an old Java, 1.0~1.1 style. Slightly better in some ways (local type inference), slightly worse in others (more magical builtins).
> Generics weren't left out because of oversight or accident, that was a conscious decision.
So were they in Java 1.0. Or C# 1.0 for that matter. Though for the latter it was because of time constraints, they were never under any illusion that they should do without.
I've switched between these camps before, and the lesson I've taken away is to use each when needed. (Altho I personally err on the pragmatic).
I've found Haskell to be very pragmatic, once I learned how to apply it. I haven't re-visited Rust in a while, but I expect to use it very pragmatically once it matures and people start developing Rust tooling for embedded work.
Against that type of point-by-point criticism, fans of a language will usually use the argument: "but that language was not designed for that!". Then the question becomes: What was that language designed for? My impression was that Go was meant to be a slightly higher-level systems language with better constructs for concurrent programming. With that in mind, it seems to me that Rust is just a "better Go".
That being said. I wouldn't recommend using Go outside of Google, Facebook or Microsoft. It solves problems, that companies and developers usually don't have. If you need always running and quickly evolving software - there is Erlang and Elixir. If you need guarantees on correctness, use static typing from Haskell. If you can resign from some guarantees to have grater control on memory, there is Rust. If you are writing in browser, there is Elm. If you want to easily transition from OO to functional programming - try Scala. If you need to prototype app for your startup quickly - there is Ruby.
Every popular language has its purpose and its trade-offs. Rust isn't strictly better than Go, but with high probability, it is better than Go for your problem.
Go is one of the simplest languages in existence. It's on the other side of the charts.
By what metric?
I can think of a lot of simpler languages. Lua, C, Forth, all the theoretical dead-simple combinator languages you don't want to use (Lambda Calculus, SKI calculus, etc.), etc...
No, not even close.
I think you might want to spend a bit more time with Rust before considering it just another C++.
Are you saying that is simple because:
1) Is so anemic and have a relatively small specification?
2) Let you solve problems in the most simple ways?
I could (maybe) kinda agree if you refer to 1...kinda.
> (no built-in — let alone syntactic — support for evented IO and CSP)
Channels are in the standard library[1], while async io is in an external package, almost everything is in Rust, and it is one of the packages that will end up making that jump to be in the standard library fairly quickly.[1]: and, isn't as big of a deal in Rust since we make shared memory significantly safer in the first place.
It's all right there. Go has good uses. But it's not good for some things including as an example for a 'good' (for some definition of good) typed language.
Also Go has generics: array/slice, map, channel. You just can't create others.
> Go supports the := assignment operator, which works like this ... All this does is look at the return type of bar(), and set the type of foo to that.
This is a misunderstanding of the := operator and how type inference works in Go. If you look at the language spec (https://golang.org/ref/spec#Short_variable_declarations), you can see that the := operator is nothing more than a shorthand variable declaration.
x := "foo"
is shorthand for (and functionally equivalent to)
var x = "foo"
Type inference is orthogonal to the := operator and is a little more powerful than the author implies. For example, Go is able to infer the type of literals, including inferring the type of a numeric literal based on the presence of a decimal point or the symbol for the imaginary number, i (complex and imaginary numbers have native support). It can also infer the type when you assign a variable to an element in array, slice, or map or when you receive from a channel. Of course it can also infer types for values inside of a struct, map, slice, or array and for keys in maps. The only obvious difference I see between type inference in Go and Rust or Haskell is that in Go you must always define the return types for functions, but there may be more differences I am unaware of. See this playground example for a demo of a few different ways that types can be inferred in Go: http://play.golang.org/p/8ep340vLky.
(edit: formatting)
I have read it :)
I think it's both misguided and misleading. It's misguided because they have the wrong idea about simplicity, and it's misleading because they claim that Go is "radically simple". Go isn't really that simple; it's just inconveniently incapable.
No, it's not your idea of simplicity. It's not wrong, it's different. That's all.
You're falling into the "my way is the right way" arrogance that so many here are accusing the Go advocates of.
People are using Go. They create content with Go, they create amazing stuff, sometimes they realize that Go isn't the best language to create this or that and so they switch to something else. What's the point there ? If a language doesn't fit your exact use cases, then it's a bad language ?
Stop the impossible standards of the perfect language. Real languages have flaws !
I don't see a similar effort to improve Go, at least not yet.
It boils down to tool support for me. If you can't have code completion and things like gofmt, no one (well, at least not me) is going to use such a thing.
[1] http://stackoverflow.com/questions/21460787/nil-slice-when-p...
What the Go cheerleaders lack is actual experience of most of the alternatives over significant time.
I have code in production based on Go, and C++, and Haskell, and PHP, and Erlang, and Python, and JavaScript, and probably others. Go doesn't really stand out, at all. If I had to pick one, I'd pick C++. If I had to add another, it would be Haskell, unless I needed front end which forces JavaScript.
Go is probably ahead of PHP, though, so that's something.
why spend time writing about something you don't like? Is it a therapy for programmers with strong opinions?
Because you may be forced to use it at work.
Every time Go has ever gotten better was because somebody who liked it thought it could be improved.
I agree that all points in the article are very debatable. But this one I'm yet to see the counter-argument.
Not really the full truth, since the monomorphic version in haskell can possibly be unboxed reducing a level of pointer indirection.
A very informative article though, thanks!
Also, the article say "Go is a regression from other modern programming languages" and I find it amusing that a significant numbers of people here taking the article and its claim seriously when it is coming from a student[1] who just finished his 'Computer Programming' university course in Fall 2014[1] (one of the reason, other reason is mentioned in the next paragraph). Don't get me wrong here: I'm not saying that you can't say anything significant when you're a student; what I mean here is that one needs to come up with more detailed explanations and with many more examples which are valid for a wide range of scenarios and use-cases when you make a general statement about a programming language which has been created by some of the highly-respected experts in the field of programming language. The list of problems mentioned in the article are important but they're not very critical for the kind of the system development that Go language has been designed/developed for[2].
Since Go language has been developed for system programming, the term 'system programming' is not restricted to embedded system only (as few people have already mentioned it in different threads here) which are mostly limited to one component (or small number of related components working together). With the advent of internet and IoT, we are forced to develop very large software systems (read, software systems as infrastructures) in order to make next generation of internet and IoT applications possible and usable (talking from business perspective). Development of these new large scale systems bring different kinds of theoretical and practical problems like complexity, concurrency and inefficiencies in system development process (for example; code compilation of large codebase and running regression test suits). And, Go has been specifically build for this new kind of large scale system softwares[2] (competing/working along with some other programming languages in this area).
Here, I would read the initial set of high-level problems which forced Rob Pike and his team to create a whole new language[2], instead of only considering issues/problems which one face while developing a single machine software/hardware program (as I've already said that they're important but they're also not everything). Once I know the strength and weakness of a programming language, I know when I should (or should not) use it, under what circumstances it's the right tool and what advantages/dis-advantages I've to trade off when I use it.
---
[1]- http://yager.io/resume.pdf
[2]- http://commandcenter.blogspot.de/2012/06/less-is-exponential...
It's too bad because a language with its general tone really should replace much of the use of Java and Python (and at Google, C++, which is still used in places where many other companies would use Java)
The creators of go only look at the gemstone from a single angle. So they never see the stain and they really don't care. When people complain to them, they just tell the complainers that they're looking at the gemstone from the wrong angle.
This isn't true at all, and is incredibly naive. Here's the reasoning behind not having generics, for example:
And the most funny thing about this arrogant attitude for some languages, is that the greatest popular tools, and the "killer apps" tend to occur in those languages.. as a indication that there is actually pretty smart people using the language contrary to common believe.
So is more likely that the "artist" might actually end using Go than Haskell