In other words, Go represents a kind of Machiavellian power play, orchestrated by slow-and-careful programmers who are tired of suffering for the sins of fast-and-loose programmers. The Go documentation refers quite often to intolerable 45-minute build times suffered by the original designers, and I can’t help but imagine them sitting around and seething about all those unused imports from those “other” programmers, that is, the “bad” programmers.
I think this is why some people dislike Go. The Go authors have made a decision about the language and are sticking to it. I get the impression that they are doing this because they believe they are 'right'. That makes some people uncomfortable because we programmers like to discuss everything, and argue, and it's hard to come up against people who have what is close to 'faith' in their own beliefs.
I think this is part of it, some of the hate comes from people that "know better" (possibly true for some, obviously the Go authors aren't omnipotent) than the Go language designers and are baffled that the language design ideas they know about aren't in the language.
But I can tell you in my experience that this type of forceful "everything is a error, no warnings" and "it is done this way (formatting for instance)" are a breath of fresh air. Having dealt with team members that barely know how to program and think a compiler spitting out an executable means it's ready (what warnings? why do those matter, it compiled), Go makes coordinating with them a lot easier. It forces them to be more correct before an executable is created. It doesn't make them better, but at least the rest of the team can work with what they create until they do get better.
Also, the simplicity of the language sure helps everybody (regardless of skill) get up to speed quickly. People that know what they're doing may hate there isn't some special feature they love (generics, etc) in the language, but working with a team of varied skill is so much easier this way.
In before "but adding generics does not make team projects harder, look at language ..."
What I like about strongly opinionated languages in general is that most of the strong opinions are around trivial features of the languages relative to the complexity of a decently interesting programming problem.
Features like formatting, no unused imports, etc.
These are typically areas in a project where Parkinson's Law of Triviality rears its ugly head in project planning meetings. Everyone feels the need to bloviate about 2 vs 4 indents, tabs vs spaces, or which lint flags to enable/disable.
Hell, with go get always grabbing the master branch, it even implicitly requires projects to keep their master branch 'green' so it doesn't break projects that depend on it. A very neat way to eliminate a whole set of "Which branching model should we use?" arguments.
I'd also say that many of these things are trivially fixed in other languages using tools. Most big projects have some code style guidelines which can be enforced using a linter and any good Java IDE can auto-clean imports lists for you at commit time (IntelliJ can be configured to auto-optimise imports just before commits for instance).
Making the compiler super strict about it seems like a good way to make quick changes awkward. Especially when there isn't a strong debugger you often end up commenting bits of code out or adding "return true" type statements half way down functions, and it's annoying when the compiler refuses to let you do it. This is one of the things that bugs me about javac - if it detects dead code in a function it refuses to compile. Maybe I'm weird but in my work this has caught legitimate dead code exactly zero times, but has triggered false positives due to transient debugging changes eleventy bazillion times. Luckily javac is dumb and you can trick it by just writing the code as "if (true) return;"
It is illegal for a package to import itself, directly or indirectly, or to directly import a package without referring to any of its exported identifiers.
>These are typically areas in a project where Parkinson's Law of Triviality rears its ugly head in project planning meetings. Everyone feels the need to bloviate about 2 vs 4 indents, tabs vs spaces, or which lint flags to enable/disable.
It was in one of the numerous Go talks/videos/presentations where I think it was Ken Thompson who said that he could walk around the Google cafeteria and hear Python programmers arguing all day long of how white space should work, and in Go, those discussions just don't happen. It's done. It's been decided. Move on.
It really struck a chord with me. It's amazing how smart people, given enough free time, will argue non-stop about the most irrelevant, insane things and stop themselves from being productive.
I disagree with you here. First, just because people are arguing about irrelevant insane things doesn't necessarily mean they're not productive. Second, I love those trivial arguments because at the end of "lunch" I've taken a break from the more involved thought, floated up to lighter stuff for a while, had some fun, and can now easily get back to the tasks at hand.
I agree with a lot of these (and would be interested in adopting a language that followed them - but one with a decent type system), but I don't think that's the Go innovation. Python had opinions about whitespace and never attracted the same level of hate.
Python's long in the tooth right now, but the first few years the whitespace thing was the source of much cursing and gnashing of teeth.
edit
More to your point, though. I would never choose a language for a project because it is strongly opinionated on such things. However, when choices lead to an opinionated language I find the feature a positive rather than negative edition....even if I find a particular decision annoying at first.
Python's whitespace has arguably produced metric tons of heated discussion on the net since Python's inception. Back in the day it was often the main thing outsiders (jwz comes to mind) rejected.
I think Python's mandatory whitespace has a similar nature as Go's unused-as-an-error. They are definitely great in production code, but when I play with code, sometimes I do want to mess them up while adding and removing the parts of the code. Even though I've used Python for more than 10 years, I often feel like "I don't want to indent these lines for now. I wish there were a way to wrap them up without changing the indentation" after copying and pasting some lines.
But then again, unfortunately, Python's significant whitespace makes automatic indentation hard, because there are some edge cases that an editor cannot extract the actual intention by the programmer well. For example, if there is a code as:
for i in range(10):
if i % 2 == 0:
print('hello')
and I paste `print('world')` after that, there are at least three possibilities of the proper indentation of the line. It can match with `print('hello')`, or with `if`, or even with `for`.
That's because Python encodes block information solely using whitespace. So, if the indentation changes, the actual meaning of the code also changes! In fact, that's why it is called "significant". You cannot automate it, just like you cannot automate writing code.
> features like formatting, no unused imports, etc.
I personally think these should be configurables turned on by default so you kind of push the new comer to write good code and build better habits but there should be an option to disable it, make it hard to find but it should be there, especially for the people like OP and other small over-the-weekend projects.
The goimports tool can be used to automagically add and remove imports to your .go source files as you work. This streamlines the casual weekend hacking use case without compromising on the benefits of disallowing unused imports.
In before "but adding generics does not make team projects harder, look at language ..."
Your (and many other people's) insistence on dismissing discussion regarding generics as some kind of a joke is anti-intellectual. You're rejecting valid criticism of your arguments on the basis that the critic's argument is unworthy of attention for some reason external to the discussion at hand.
I agree that pro-generics arguments are usually boring, and at least 90% of what they say has been heard before. But the same can be said of Go evangelism, like your comment; they are no less worthy. Please don't deliberately shut down discussion.
I don't even get the vitriol against generics - the designers have only taken a "not now" approach to the subject and everyone acts as if Go is a social experiment to get everyone mad about generics.
Then people bring Rust, which has only had a stable grammar for last couple months and a standard library nowhere near Gos. Would it be wise to complain that the Rust stdlib doesn't contain a HTTP server implementation?
It's not just the "not now" approach. It's the rhetoric that often goes along with it. The author of this piece picks up on it when he talks about the "we've already thought about this and we're tired of talking about it" vibe, though I might characterize a lot of the discussion around generics from the Go community at large more specifically as "you think you want/need this, but trust us, you don't, and the inconveniences you think you're experiencing are just not that big a deal, particularly compared to the inconveniences you'll experience if we do add it."
And yes, if not having an HTTP server implementation in the stdlib seems like it makes your project difficult, that's a perfectly reasonable criticism of Rust.
(Though one I suspect will get resolved much more quickly and cleanly than issues like generics in Go.)
> I suspect will get resolved much more quickly and cleanly
It's pretty easy. You just add this line to your Cargo.toml:
hyper = "0.3.14"
And the next time you build, Cargo handles everything. You can now use hyper like any other library that's included with Rust, no biggie.
This is one reason we've chosen minimalism for the standard library: It's really easy to use external libraries, and once things land in the standard library, they often don't improve much. The versions become tied to the compiler versions, contributors now need to build the entire compiler rather than just working on a single library, and everything else. We've already seen three distinct major HTTP implementations happen, had we put rust-http right in the standard library, we'd have frozen something the author has already deprecated!
Choosing non-minimalism has advantages too: in this scenario, you need to know that hyper is currently the best library, for example. Engineering is all about trade-offs.
(Solely chiming in on the HTTP in Rust thing here. I found the part of the article about the Gopher... lacking, and it distracted me from the rest of the author's points.)
no. there is a HUGE difference between std lib and third-party libs. Std lib is like a contract - maintainers of language have to keep all parts up to date and working. Maintainers of third-party library can write "Farewell Rust" blogpost and all projects, based on that library will be in trouble. And as http is a very important thing for web-programs, it's much better to see support of http in std lib.
> Std lib is like a contract - maintainers of language have to keep all parts up to date and working.
Rust has language stability (in practice right now, and officially once we hit 1.0 in a month), so we in fact do guarantee this.
> Maintainers of third-party library can write "Farewell Rust" blogpost and all projects, based on that library will be in trouble.
Languages can do that too, in which case the entire language and its ecosystem is in trouble. Anything can be abandoned. The crucial thing is that if a piece of infrastructure is in the standard library, then it's much harder and slower to iterate on it. HTTP is a fast-moving standard (see HTTP 2, for example), and so it's very important to be able to iterate quickly to support new features.
> And as http is a very important thing for web-programs, it's much better to see support of http in std lib.
I disagree. Web applications need HTTP, but many applications aren't Web applications. As a example on the far opposite end of the spectrum, your OS kernel doesn't have an HTTP stack in it (unless you happen to be running something like khttpd), and Rust is designed to be usable for OS kernels. Large standalone standard libraries reduce flexibility, and Rust is designed to be flexible.
Hmm... Windows has part of a HTTP stack in the kernel, which I know solely based on hearing about the recent vulnerability in it. And OS X's kernel, IIRC, can load disk images over HTTP for netboot purposes. That leaves Linux as the odd one out :)
(Yes, I know that's completely tangential to the point you're making.)
Languages can abandon own std lib? Keep away from such languages.
> HTTP is a fast-moving standard (see HTTP 2, for example), and so it's very important to be able to iterate quickly to support new features.
Golang doing it just fine, so Rust can too.
> I disagree. Web applications need HTTP, but many applications aren't Web applications.
I'm talking exactly about web applications, not about all applications. And if web applications is not the field of Rust - let us know about it. Right now is not obvious and even web frameworks exist in Rust.
Languages can abandon own std lib? Keep away from such languages.
Not abandon their stdlib. Be abandoned. There is nothing more preventing developers of the compiler/vm from abandoning their efforts than the developers of a library. It would make little sense for developers of the language to abandon just the stdlib, as it is part of the language.
I'm talking exactly about web applications, not about all applications. And if web applications is not the field of Rust - let us know about it. Right now is not obvious and even web frameworks exist in Rust.
Rust is a fine language for web applications, but it's not designed specifically for them. The languages with huge stdlibs date from a time when accessing libraries was much harder than it is today. The internet, as well as package management, was young when Python and Java were born. Now that it's easy to download packages, and we have reasonably passable tools for doing so, there's no need for heavy standard libraries.
Go is specially designed for running on servers and performing network tasks. So it makes sense that it would have a stdlib with rich networking support, including http.
Node was designed as a frontend to libuv, to make nonblocking IO easier to use. The most visible domain where nonblocking IO is extremely useful is in making web applications, AND the fact that it's javascript makes it even better suited to web. So Node has http support baked in.
Rust is meant to exist in the same space as C++. It can be used for anything. OS kernels to text editors to web applications. There is nothing in particular that ties it to any of these domains. It has the option of putting support for all of these in the standard library, which would make it hard to maintain. Every time one part of the stdlib needs to change, the language needs a minor version bump, or there's a delay before anyone can use the new libraries. Not a big deal when you only have one or two domain specific components in the stdlib, but a problem when you have twelve.
If the stdlib supported only some specific domains, it would give people from other domains the impression that they're second class, and drive them away. Not cool.
Language can be abandoned, but it's pointless argument, sorry. When language is abandoned, there's no reasons to argue about any aspect of that language.
In second part of your comment you comparing stdlib and external libs as they are equally reliable, but my point is exactly about difference in this aspect. I agree stdlib shouldn't be swiss knife, but I disagree it shouldn't have nothing except minimal set to serve language constructions. Go was designed as C++ also, not only for networking. And it has image module, not only http (for example). I see how fast and successfully Go evolving, I think Rust is better and that's why I think it's the area where Rust can take better idea from Go.
I would argue that Rust's approach is perfectly fine so long as they have strong organisational support around third party libraries. Look to Java for how to do this. Many core Java libraries are managed by Apache or Eclipse e.g. HTTPClient who manage the process around open source projects.
HTTP clients are not something I would want in a standard library to be honest. Since there are so many different ways to implement them. And not all work for all use cases. It's not the same as StringUtils or ArrayUtils.
Why not let a bunch of third party HTTP libraries pop up. Eventually things will converge on the "best" library for doing http in rust. Open a discussion and start adding great third part libraries to the std lib. The challenge then would be keeping this coherent throughout the std lib.
Not sure why you think I don't want to let libs pop up. I just ask for http module in std lib, not as the only implementation which can exist, but as "last resort", always working, in any new version of language, supported and tested by core team maintainers. Not full-featured thing with routes and other whistles and belts, just basic things.
Haskell does it the way Rust does and it's pretty frustrating to have tons of solutions to evaluate for everything you want to do. Maybe crates.io will have a better discovery story, or rust will have a larger user base that makes it more likely that there's a clear winner. I hope so.
> I don't even get the vitriol against generics - the designers have only taken a "not now" approach to the subject and everyone acts as if Go is a social experiment to get everyone mad about generics.
I don't use Go so I don't really care about their generics or lack thereof. What I found ... odd ... is how the Go team has apparently said they can't go generics because there's no good way to implement them. Seems like a strange thing to say when many languages are happily using them.
Implicit interfaces make generics a lot less trivial to implement. They also don't want to simply add an existing approach with bad trade-offs (see C++ templates). Likewise, adding a runtime based multi-dispatch based generic system is not much better than what we already have.
Lot's of languages have generics, but they have trade-offs, so they aren't free, even if they can implement them using existing generics implementations. Picking what they're willing to sacrifice can be hard, even if it's something like slower compile times.
Anything backwards compatible has to be in Go 2 or later, because generics are hard to make backwards compatible, we'll have to wait.
After hacking Rust, I got the feeling that generics are hard. They are so hard that a language should consider them from the beginning to fully take advantage of them. That might be the reason why the Go team says generics are hard to implement in the current Go type system. They can also choose either C++-like code generation based on templates, or external code generating tools, but both are not perfect in my opinion.
And library can be easily abandoned or just be broken after breaking changes in next version of language, and you will have to wait couple of months, while this issue will be solved. Or just fix all the things yourself.
> after breaking changes in next version of language
In practice Rust doesn't make breaking changes anymore. (It hasn't since beta, and in a month or so 1.0 will be declared officially stable and it will become forbidden to make them.)
Various core Go team members seem to have a different philosophy regarding generics. They actually don't have a united front on this.
It seems Russ Cox and Rob Pike are either anti-generics or in the you-dont-really-need-them camp, but Ian Thompson and Brad Fitzpatrick have seemed very open to the idea - what they can't, however, agree on, is exactly how to implement them so that they make sense in Go. That's it.
If you or anyone out there manages to produce a proposal of how they should work/look like and even a fork of Go implementing the idea, it will be taken seriously, at least by some core Go members.
I have a feeling that generics are coming. And I have a feeling they'll be very Go-like - an external tool with code generation, not special syntax. Just my 2 cents.
I think adding generics to a stable language is actually a hard thing to do. There's more than "that's it". Rust has had many major and minor changes regarding generics solely, which has broken backward compatibility each time.
The Go team may find a brilliant way to accomplish this, but I think the only viable way left is, as you said, using code generation. Either C++-way, which is a special syntax but still a form of code generation, or an external tool. But neither of them is elegant, because you cannot fully utilize the convenience that the type system give. These might be the concerns that the Go team has.
Maybe the "elegance" is a factor as well, but I haven't seen it mentioned. All I've seen mentioned is: a) can't change syntax b) can't take huge performance hits at run time or at compile time c) can't break backwards compatibility d) talk is cheap - provide a working implementation
So far, nobody has been able to show all 4 of these requirements, so nothing has been done.
But when/if someone does, I expect it to be taken very seriously.
Almost. So close. But no cigar.
Go generate is for the package creator, not the package consumer. So you, as a package creator, may create a "generic" red-black tree, but unless you pre-generate all my use cases for all my data types, I can't pull your package and then use go generate to create Tree<int> and Tree<string> if that makes sense.
That comment was there because my point was not about generics, but about programming language features (that are must have, the must have list of course being different for everyone) in general.
> Agreed. Go lacks many things, but the "zen" of Go is wonderful feature most people aren't aware of, or under appreciate.
It's funny that you use the word "Zen" - about two years ago, I gave a talk about Go to the New York Python Meetup about why I switched to Go[0], and the punchline was that Go fits the Zen of Python[1] better than Python does[2].
[0] Before anyone gets upset - they asked me to speak, and they were genuinely happy with the presentation. It's not like I went in there to troll with a talk on "This is why your language sucks"!
Personally, I think people dislike Go because they try using it for tasks where it makes their life miserable. Mainly for web programming. (unless of course you're a masochist and enjoy not having a repl and want static typing and a compilation step when recursively parsing unknown json data structures).
In my experience, Go is a tool thats really good for a certain set of programming tasks and like all other languages really bad or annoyingly painful for others.
For me, Go is my number one tool for creating command line apps now. I get immediate cross-platform cli tools with zero headache. Its also a really nice fit for lower level networking/distributed applications where you are working with byte protocols (things like mozillas heka, or docker, proxy servers, chat clients, etc), the networking server-side stuff where you would probably have used C++/Java.
My recommendation would be, if you work a lot on this kind of software seriously start using Go, you will love it and think everyone is crazy for hating on Go.
The problem is I think lots of people are trying to use Go for stuff it is not designed for and where, compared to the alternatives, it is a rather bad fit. For instance Go is zero fun for: Compiler Programming (Haskell/C++ have way better tooling), Games (libs are one thing but Go cannot compete with C++ perf here), Desktop GUI apps (Just use QT), Mobile Apps, and Web Programming (take your pick of python,ruby,js,clojure,php - your life will be much easier), Hardware/Low Level Systems programming (Obviously you can't use a GCed lang here).
I haven't found another area where I really like programming in Go besides CLI and networking I mentioned above. It could have another sweet spot I've missed...
> unless of course you're a masochist and ... want static typing
Some people say to prototype in a dynamically-typed language and then switch to a static language later. Dynamic typing might save keystrokes, but typecasting and type-checking do require lots of typing, and who cares that much about a few hundred extra keystrokes anyway?
Some people say to create whole, large apps in dynamically-typed languages, but those people clearly haven't tried modifying or debugging code bases in those languages that weren't created with utmost discipline and 100% test coverage.
So with 10 years of web programming experience, I'd emphatically argue that masochism is not using static typing.
I have warm, happy dreams of a future where there's a great alternative to the dynamic/weak web languages of today. There are already some great entrants, but nothing has reached the massive popularity of existing languages yet.
I think you left off the key part of his point, namely "when recursively parsing unknown json data structures".
json parsing in Go uses reflection, which not only means it is slow, but if your input is not consistent (like say.. a log file with 20 different possible formats), it can be quite painful and very verbose.
I believe you that it's slow, but I'm not sure I know enough to understand how it's a knock against Go as a language. Is it something that's impossible to fix without changing the syntax?
Anyway, you could always use a highly-optimized JSON parser written in C[1], so it shouldn't be a deal-breaker for anyone interested in Go.
In my own testing it was faster (even with ffjson) to pre-clean my data in cpython or pypy, and then emit some intermediary format (like capnproto) for the go code to consume. I was parsing huge files full of lots of non-uniform json with many formats.
For most use cases though, the fact that json is "slow" is probably not a huge factor, as network IO or something else is likely the gating factor. For those uncommon cases though, I wish the native json lib in Go was faster.
"Web Applications" are often made up of parts now. So while php/ruby/python are faster to develop for most things - writing the websocket handler or AJAX polling API in Go makes a LOT more sense given the performance of these crucial parts of the application.
I am currently using the massive PHP + Node.js ecosystem for most of the application and Go for the critical communication parts.
I second this approach of mixing components. While I have not personally used Go, I have used Tornado and C++ to handle complex networking code, and I'd never use these as a complete substitute for "web application" development.
My current company's web API is built using Django, which may come as a surprise since we also do realtime stuff, but that's the benefit of mixing the best tools for each job.
I enjoyed that the author readily admits to his own faults concerning Go too:
In this telling, the story of Go is really a tale of revenge, not just against slow builds, but against all kinds of sloppy programming. Which in my opinion is too bad, because I myself am a sloppy programmer.
This really does seem to be the approach I see with the Go digest mailing list. What I don't understand though is the ease of importing a library, say from Github. Interesting that the language from the author is all about how rigid and unforgiving Go is, yet "some guys" libraries can just be thrown into the mix in your program, and Go has no issues with this.
Go is developed inside Google where all dependencies are checked into their global version control repository. There are literally no versions inside the Google codebase - everything is compiled at head. If you want to upgrade a third party library then you are expected to globally upgrade every user of it .... simply bumping the version of a widely used library can thus turn into a multi-month promotion worthy project!
Given this background and the Go designers focus on Google's internal needs, it's perhaps not surprising that you can import code from github .... but not specify which version you want. (unless that is now fixed?)
> If you want to upgrade a third party library then you are expected to globally upgrade every user of it .... simply bumping the version of a widely used library can thus turn into a multi-month promotion worthy project!
The alternative is of course supporting dozens or hundreds of copies of a library and every possible commit hash of said library. I contracted at a python shop that had 81 versions of a single library in use all pinned at different versions. The reason I know this is that I had the great joy of dealing with upgrading all of them after a critical hole was not only discovered (the company knew about it for some time, but just didn't want to bother updating all those apps) but exploited... repeatedly.
> it's perhaps not surprising that you can import code from github .... but not specify which version you want. (unless that is now fixed?)
If by "fixed" you mean there are dozens of solutions to pin versions -- then yes. If you mean baked into the go tool, then no.
But - but! Saying that you want your org to use one version of a library at a time is one thing. Saying that you want your code to use the latest version of every library is another thing altogether, however, and that's what "no version for github code" does, right?
"One version per org" means "upgrades are harder, but patches are easier and you don't need to deal with different quirks of different versions at the same time and you don't get problems using 2 components that need 2 different versions of some other thing in one process etc."
"Latest version, always" means you have no way to even build the latest version of your thing that was tested and is known to compile and work. Kinda sucks, I think.
Yes, I didn't pass judgement on the approach. It works well enough for Google and avoids problems with e.g. ELF symbol conflicts. For development out on the open internet you do need some way to specify versions so it's a puzzling lack, but "if it works for Google it works for you" does seem to be a recurring theme in the Go design.
> Given this background and the Go designers focus on Google's internal needs
Does it mean the community isn't a priority? this vertical relationship between the Go team and the community could doom the language as fast as it was made popular, that's my opinion.That's a real issue.
That has always been the point of go. A better way of writing code the 'Google Way' It is really useful outside of that (I use it for everything other then video games), but it was always a language to help them get their work done faster.
The best example of this for me is the initialism style rule:
> Words in names that are initialisms or acronyms (e.g. "URL" or "NATO") have a consistent case. For example, "URL" should appear as "URL" or "url" (as in "urlPony", or "URLPony"), never as "Url". Here's an example: ServeHTTP not ServeHttp.
> This rule also applies to "ID" when it is short for "identifier," so write "appID" instead of "appId".
> Code generated by the protocol buffer compiler is exempt from this rule. Human-written code is held to a higher standard than machine-written code.
To enforce this in the linter they literally define a list of initialisms[1].
It's certainly difficult; every time I have to tell someone their opinion is wrong they get defensive. Look, I'm just trying to educate you. I'm right so let's just end it at that. :)
"Opinionated" frameworks/tools/languages are becoming pretty common these says. I would say programmers are becoming quite fond of authors who just make some damned decisions.
Endless arguing over 2 vs 4 spaces or spaces vs tabs has not really advanced the programming industry very much, despite being highly democratic. For a lot of these small decisions, it doesn't really matter what you choose as long as a choice is made and it's consistent.
> we programmers like to discuss everything, and argue
I doubt that, for the sake of truth and not just to argue with you. Most programmers do not want to argue or discuss things. Most programmers leverage knowledge and understanding to make the computer do interesting things. Some find go more understandable and useful than others.
I remember when Go first came out and I thought "wow, that looks interesting, I'll check it out", then when I was checking it out, I found that the language enforced placing opening curly braces at the end of a line rather than wherever you want, such as at the beginning of the next line (which I generally prefer).
There was no option to even be flexible about this, for example, by programming one way and then using gofmt before committing code, because you will literally have an incorrect program if you put the opening brace on the next line due to automatic semicolons placed at the end of lines.
I find it amusing that people would use the term "incompetence" to describe Ken Thompson and Rob Pike. These two guys have been as instrumental in shaping modern computing as Linus Torvalds, Bill Gates and Steve Jobs.
But I guess it's easy to be critical of other peoples output when you're an anonymous internet user yourself.
Sorry, I thought it was clear - incompetence regarding [modern] language design. They don't deny this neither. And it seems they're even proud of this.
I don't think your amended statement is much better. They have designed a language that meets their goals. They have decided not to include many things, but that does not mean that they are not aware of them, or are incompetent for doing so.
Which is why Go has goto's and pointers. Got it. No, Go's adherents are just sloppy in a different way. I have many bad things to say about Haskell, but I admire Haskellers lack of sloppiness. I cannot say the same about Gophers.
Go's goto is the standard structured-programming-limited goto which is not allowed to violate blocks, which means it is not the goto that is "considered harmful". Go's "pointers" are not allowed to do pointer arithmetic, which basically means that they are references. As they are also backed by a garbage collector, this means you can't do any of the nasty C things you can do with them, not even "fail to deallocate" them. All you've got left is "unexpected liveness" (a.k.a. "memory leak") and that can happen to anybody, even Haskell.
You can dock a couple of points for pointers being allowed to be nil. You may want to give half-a-point back for the fact that a nil pointer can actually be a valid implementation of an object, and I actually use this quite a bit. But nil maps can be accidentally unpleasant.
Goto's create unreadable code and are unnecessary. They're there to encourage the writing of bad code.
You can pass a pointer over a goroutine channel. That's my main issue with them, beside the fact that we should be past this needless complication of our code. Again, they're unnecessary and encourage bad code.
No, gotos are present to allow you to use programming paradigms other than structured programming, isolated within the confines of a structure-programming function. The most popular such alternative paradigm that can be written by a human being a finite-state machine, which can be quite clearly and efficiently expressed via goto. Generated code can also get a lot of mileage out of goto, and this is usually code you're not going to be touching anyhow if you've gone so far as to generate it.
This paralyzing fear of goto is really out of date. I work on a Perl code base with dozens of other programmers of varying levels of skill across man-centuries of programming the vast bulk of which has basically had no code review. I've seen enormous quantities of bad code and had a hand in cleaning up a lot of it. I've seen confusing object hierarchies, bunches of confusing functions calling each other with essentially untyped parameters, all of them "fixing up" each other's parameters (mostly "correctly"...), functions a mile long with nothing but the occasional incorrect comment, reams of dead code kept around "just in case", and a huge variety of other bad code practices. And you know what I have literally not seen once? An abuse of goto. Nor do I see it in the open source I crack open, nor anything else I read.
Even if someone pops up and claims they see goto abuse "all the time", I'd challenge them to go find the source for them, and I bet they find it was just one person doing all of them in their code base. People do not abuse goto anymore, because if anything, they've been beaten so thoroughly into compliance with "goto is bad!" that the problem they have with it is not using it when they should. I don't fear that putting goto into a language will suddenly produce tons of code where entire programs are just one big function with tons of gotos in it, because I observe that it doesn't happen, and observation of facts trumps any theory about how the facts "could" be something else, because the facts are the facts.
As for passing pointers, yes, it can be dangerous. So far I've had no trouble with it because I'm always also passing ownership, but you do have to know what you are doing. I used to pine for Rust's feature set, but then, I observe that it turns Go into a completely different language, so now I prefer a world in which they are both available.
I do see a bit of goto use in the PHP community, but it tends to be used by well-known and respected programmers, sometimes just to make the point that goto isn't evil in and of itself.
> Goto's create unreadable code and are unnecessary. They're there to encourage the writing of bad code.
Goto's are seldom used by bad programmers anyway - most of them wouldn't even be aware of them. They generally exist in languages as a niche feature used be experienced developers for those rare situations where a goto results in cleaner code. You definitely don't see Go developers sprawling goto's everywhere just because it exists.
> You can pass a pointer over a goroutine channel. That's my main issue with them, beside the fact that we should be past this needless complication of our code. Again, they're unnecessary and encourage bad code.
Erm, sorry. You've lost me now. I'll grant you that pointers require a little extra mental overhead, but they're most definitely necessary when you're writing code that either needs to be sensitive to memory usage, or performance.
As for pointers "encouraging bad code", I'm not even going to dignify that remark with a proper response.
> Goto's are seldom used by bad programmers anyway - most of them wouldn't even be aware of them.
.....yeah.
I've seen too many internal codebases where "goto" was used so horrifically I want that feature to die in a fire just to prevent such malignancy in the future.
Golang only hasn't reached that stage because its young enough there isn't heavy maintenance work over a 10+ year period yet.
Goto's are used extensively in the Linux kernel for clean exits from functions (typically system calls) that must validate parameters, allocating resources as they go, but then abort if there are any errors in the parameters. For example: http://lxr.free-electrons.com/source/kernel/fork.c?v=3.3#L42...
>Goto's create unreadable code and are unnecessary. They're there to encourage the writing of bad code.
That's the old wives tale about gotos. Mostly repeated by freshment that heard gotos are bad, don't understand fully when and why they are bad, and repeat it as cargo cult gospel.
In my organization Goto's have to get past code review, which is rare and when they do make sense they are probably good option. Your organization can have its own style guidelines.... Just say no gotos- done.
> Go basically forces you to have clean code all along,
> which is a bit like forcing a scientist to wipe down the
> workbench and rinse all the beakers between every experiment,
>or forcing a writer to run the spell checker after every cigarette.
As usage of gofmt is idiomatic Go, simply using the superset goimports handles all of this for you.
Sure, any language has tools to reformat code for you in some magic ways - but what makes Go special is that it takes this kind of tooling seriously enough by making it standard right out-of-the-box and right when initiating new users to the language (notice the [Format] button on the first slide of the official Go tutorial http://tour.golang.org/welcome/1 ).
Your sarcasm is noted. I believe hahainternet was referring to articles that either gloss over the bad parts of a thing, or make specious claims to reinforce their ideas.
IMO, there are two different opposite directions in programming languages and tools approaches,
1) The artistic approach which is very flexible and requires creative thinking and deep understanding of the essence of computing. However, you can easily shoot yourself with it. Languages of this type are for code guru, knights and hackers.
2) The engineering approach which has rigid rules for efficiency and social cooperation. It is less error-prone but tend to suppress diversity and discovery. Golang belongs to this category. To me, the core Go authors are more of engineers than artists :)
I use Go for work and simple command-line tools for myself. It is also great for cooperation in well defined scenarios, e.g., Web back-end service. When it comes to creative works, I'd rather avoid it.
No, the Go programmer will win. Strong(ly) type(d), you see :) #SorryCouldntResist
Note: Said without any bias towards either Go or Perl.
Also, I'm not a language lawyer, and this was a joke, so I'm not replying to any comments about Go not being "purely" or "strictly" strongly typed or whatever.
Go is not a perfect language, but I've been hard-pressed to find one and so I've stopped looking. Here's what I like about Go.
Go is crazy boring. You type things. You hit return. You type the next thing. Error not nil? Type more.
There's something very sequential, linear, methodical about it all. I suppose in part it's gofmt. It may also be a byproduct of any strongly typed language, but unlike many of those languages, Go feels simple and reasonable.
I actually think this is how programming serious applications should be. A little boring. Nothing too fancy or cute. No refactors to fit some new great abstraction pattern.
Not to wax nostalgic — in fact, I can't, because I wasn't even born — it reminds me of paper tape in old computers. The card gets punched, it feeds in, and the computer considers and executes your instructions. We're still doing that, really. Programming should be simpler. Sometimes I think we go out of our way to make it more complicated because we are experienced and bored. :)
>Reading Go’s mailing list and documentation, I get a similar sense of refusal-to-engage — the authors are communicative, to be sure, but in a didactic way. They seem tired of hearing people’s ideas, as if they’ve already thought of everything, and the relative success of Go at Google and elsewhere has only led them to turn the volume knob down. Which is a shame, because they’ll probably miss out on some good ideas
This captures my sentiments and experiences with the language perfectly.
The point about Go being too pedantic and thus hindering exploration is something I've felt too. Some of that pain was mitigated by the Sublime Text Go plugin that has shortcuts to add/remove imports.
Yes, it was very funny and informative. I let out an audible sound when reading some of these one-liners:
> It is possible, however, that the Go team has developed a set of secret signifiers to distinguish these constructions in everyday conversation and not told me about them.
or
> At first I wrote my methods on the values, which seemed like the normal, American thing to do.
Someone posted yesterday about how to pronounce hexadecimal numbers. It's funny because somedoby, somewhere has a lexicon for describing the different overloaded loop types. sidenone: i find overloading cheap or sort of a cheat. I understand it in the content of typed languages, but in something like JavaScript or PHP it fucking sucks.
This is generally a tradeoff you have to make in programming language design. Should the checker enforce good code or should it let all but the most broken code through in the name of exploratory programming?
I would recommend using Python or possibly Clojure to experiment with and then translate the code to a language that will help you catch bugs (Ada/a functional one) when you know exactly how the problem is solved.
Two tips about the pain points regarding unused imports and variables:
The program goimports is an extended version of gofmt that will automatically add and remove imports. Bind it to a keystroke of your editor of choice, and the imports situation becomes painless.
For unused variables, you can do "_ = someVar" to stop it from being flagged as unused. Still a bit of a pain, but much easier than commenting and uncommenting things all the time.
Great article. However, I would not assume that us (good programmers) vs them (bad ones) is how the go folks see the world. If a couple decades of programming have taught me anything, it's that "them" is usually "me" or "past me" or "500 of us".
A good point. I've seen people say that the Go designers are designing a language for "bad programmers", but maybe they're just designing for humans. Maybe code readability is more important than conciseness.
Catching unused variables is pretty essential, it's easy to shoot yourself in the foot by redeclaring a variable with := inside a block.
>> which means you have to need separate storage for the actual RaceCar and GetawayCar values, either on the stack with a temporary variable or on the heap with calls to new
Maybe I miss his point here, but in Go it's totally valid to just create a new *GetawayCar with &GetawayCar{} in any scope. You can return that pointer from your current method. It's not necessary to explicitly put your GetawayCar on the heap with new(), Go will decide for you with escape analysis.
> Go is productive enough that I’ve been enjoying implementing things from scratch like collapsible widgets and navigating a viewport. In order to do evil things like convert raw bytes to floats, I chose to use the “unsafe” package, which made me feel manly, powerful, and highly supportive of private gun ownership.
My workflow at present is to print out the hex representation of a binary file onto physical sheets of paper, and then mark them up with a ball-point pen that I received last year at a conference about technology.
I love writing like this, where you got that pen doesn't matter one bit, yet it turns the drab of a tech blog into an enjoyable story to read.
Ever since I started immediately creating at least one "test" file in my Go projects, I have found that both the unused variable/imports problem, as well as the "freedom to explore" issue have been eliminated for me.
Sure, they will still bite me in that individual test file if the situation arises. It keeps the problem out of the "real" code, however so I don't get it when building. In this way I get to maintain a creative space to test out various apis and do my "print to console" testing, while also keeping my primary code base Go-Clean™.
There are unused imports, solved easily with goimports, and then there are unused variables, which AFAIK are not solved by any tool. I dig what the author says regarding "explorability" hindered by all those errors popping up.
It's also funny to see errors solved automagically by tools instead of manually by the developer; there used to be a time where IDEs where voluntarily avoided because they did too many magic things to your code and to your project, and true hackers should be able to work with only a text editor and the compiler. I fear go may be headed back to IDE-land if it starts relying too much on tools (we have goimports today, the go generate command is to be used for code mangling before compiling ...)
> I fear go may be headed back to IDE-land if it starts relying too much on tools (we have goimports today, the go generate command is to be used for code mangling before compiling ...)
I think that it's kinda the opposite: rather than one monolithic IDE, it's lots of little pieces working together. Pretty much what one would expect from the guys who brought us Plan 9 and Go…
I am worried that there might be a dangerous trend in conversations about go on HN recently. There seems to be a tendency toward ad hominem comments against the go authors.
The article itself is a great read. I love hearing interesting and honest commentary about the language. But I wonder if comments like "for reasons that appear to be political, does not have integer Min and integer Max functions" are appropriate. Later the author mentions "I get a similar sense of refusal-to-engage — the authors are communicative, to be sure, but in a didactic way." If the go community (or the programming community at large) truly has the sense that the go authors are unwilling to engage with the users of the language, then that's a big problem. However, are these sort of off the cuff comments the right way to start a discussion about it? At the very least, I wish that the author would provide specific evidence for these claims. I'm sure that there is some justification for them, but what the author is telling us is his inference, and I would appreciate an opportunity to read the source material and decide for myself. FWIW I have been programming in go for 2.5 years and made a few trips to the go-nuts mailing list. I don't share the author's impression, but I also haven't read every thread on the mailing list.
That's far from the worst of it, of course. I have read comments calling the go authors arrogant, ignorant, or conceited. If you insist on criticizing the go authors, I would hope that you could at least keep it professional and provide a link to some comment/literature to back up your criticism.
I welcome criticism of go, or of any topic for that matter. I just want to avoid unfair characterization and irrelevant ad hominem comments. Am I being too defensive or do other people share this concern?
> However, are these sort of off the cuff comments the right way to start a discussion about it?
Well it is a persons' opinion. There are some facts, some humor, some personal opinions. I am not sure the author planned on being on the front page of HN. I don't think he submitted his own article. It is up to the readers to put things in the appropriate "bins" so to speak -- "This is good advice", "I don't like this part", "This is just a personal attack" and so on. Sometimes the same article can contain a variety of things.
From what I can gather on the mailing list threads, the language designers are against polymorphism, as well as adding letters to function names, so unlike the standard C library which operates on float, double, and long double, as well as int and long where appropriate (e.g. absolute value), the Go standard math library operates only on float64.
This author is quite exaggerating a bit. It seems like he himself is constantly preoccupied with politics. Fine. But this doesn't mean other people who he see with his eyes are necessarily thinking in the same pattern. "Machiavellian" is such a heavy word. Go started out with a purpose, a purpose which makes a lot of sense. It's not all about "make a new language and shove the new rules onto everyone by coupling it with Very Fast Build Times, a kind of veto-proof Defense Spending Bill in the Congress of computer programming." Such a design has a lot of practical value.
I used Go at work to write some utilities which extracted and manipulated values from large text files. It compiled fast and ran fast (at least, compared to the Python it was replacing).
However, I learned that Go is a language conceived for Programming in the Large, and I found out (once again, thanks Java) that I don't like languages for Programming in the Large.
But if I liked that sort of thing it'd probably be one of my first choices.
The former being much more concise, so that you can display (and grok, perhaps) a single function in 3 or 4 lines, vs the Go style, which can result in extremely long functions (long because they do a few things, and require error checks before and after each one, and so on, rather than being long for actually doing a lot).
The single line version implies at the beginning that all the line does is return. The longer version requires you to read the whole paragraph to figure out what it does.
Doesn't compile though. You'll need lots of extra lines just to see an output, which is really much of what the posted article was talking about with its wandering-eyed gopher tale...
package main
import "fmt"
func main(){
fmt.Println(name(28))
}
type T struct{name string; valid bool}
func get(ref int64) (T, bool) {
return T{"abc", true}, false
}
func name(ref int64) string {
switch data, ok := get(ref); true {
case !ok:
return "No Data"
case !data.valid:
return "Invalid Data"
case data.name == "":
return "New Data"
default:
return data.name
}
}
I'm completely baffled that people find the ternary operator difficult to scan.
The concept is simple. The syntax can be terse, but it doesn't have to be. Modestly capable Excel users take advantage of something just like it.
The only time I've ever seen it become difficult is when either the conditional or result expressions get hairy or depend on undescriptive variable names. And when that's the case, well, you're going to have the same problem with the expressions in your if/else, albeit spread out over a few more lines by convention (which one could do with a ternary expression just as well).
I'm at the point where I suspect complaints about the ternary operator are a cargo cult repetition thing, and the developers who are scared of it are scared because they were either taught by someone else to be scared, or they're suffering from a confirmation bias problem where they notice confusing conditionals more when they're associated with the operator.
> The only time I've ever seen it become difficult is when either the conditional or result expressions get hairy or depend on undescriptive variable names.
It's definitely possibly to write obfuscated ridiculous code without the ternary operator -- but I think that's part of the whole "go-lang mentality".
Would I leave unused declarations in production code? No.
Do I have a problem with a compiler that doesn't let me test code with a function call commented out without also commenting out all the other variables/functions that are now unused as a result? Yes.
> I'm at the point where I suspect complaints about the ternary operator are a cargo cult repetition thing, and the developers who are scared of it are scared because they were either taught by someone else to be scared, or they're suffering from a confirmation bias problem where they notice confusing conditionals more when they're associated with the operator.
I definitely don't think Rob Pike and Ken Thompson are getting confused -- it's more like they took a utilitarian view of the situation and decided - if the average code-base is made better or easier to read by this change, then it's worth it.
The over-all result is a language that appears to be easy to pick up and productive at least for those who use it - but it's hardly exciting or fun to code in.
It's not a cargo cult thing, it's inherited wisdom borne out by painful experience. Like goto and braceless single-expression blocks they are so easy to misuse that they can easily be much more trouble than they're worth.
Simple ternaries can be useful in trading off the unreadability of verbosity for the unreadability of compactness. Real Programmers should know how and when to use them. But nested ternary expressions are basically trolling...
It's just syntactic sugar for if-else though, so it's right in the sweet spot of "doesn't make a big difference either way" and "is subject to preference" that makes it a prime target for bikeshedding. Personally I don't like the ternaries either, typically the syntax is ugly, but the if-else seems only slightly better to me.
The ternary operator usually appears in imperative languages (or should I say, languages which are not expression-oriented) where the if-then-else construct statement is NOT an expression, and possibly has side-effects. Therefore, you need an alternative construct that really is an expression and evaluates to something.
The syntax itself is irrelevant. If you can say the following in your favorite language:
x = if (condition) { something } else { something else }
> If I had to guess, I’d say the Go gopher suffers from a mild form of autism.
> I get the same feeling about the Go language. It feels like it is designed by an obsessive personality — obsessed with build times in particular, but also having an obsession with detail, someone who rarely makes mistakes when writing code, who generally will not run code until it appears to be complete and correct.
WTF? Not only is it insulting, it's ignorant. Considering some of the other comments here regarding how "excellent" this article is, it clearly doesn't concern many when casual insults are allowed.
No no, let's applaud someone for making casual, racist-like remarks without even questioning it. If this is considered quality, we should be ashamed.
As a high school teacher, I work with kids on the autism spectrum all the time, and I don't find his comments offensive. They seem relatively accurate, too.
I think he's saying "overly concerned with detail, marked lack of eye contact; probably on the autism spectrum." These are literally two of the diagnostic criteria for 299.00 Autism Spectrum Disorder.
It seems like you're reading a negative connotation into the "autistic" label that isn't present in the article. Calling the gopher "unsettling" is the biggest insult I can find in what he wrote.
I don't find the second part problematic, but I agree completely on the autism remarks. I started reading this article and got to a section titled "Go's Autistic Gopher" (paraphrased) and immediately closed the tab.
The author could have used plenty of other adjectives but had to use a medical condition.
I didn't bother to read the rest of the article even if it supposed to be entertaining. I didnt feel like sifting through other offensive comments (seems there may not have been others) so I skipped it.
Also seems oddly tone deaf given how common ASD seems to be among techies and their immediate family.
I think this is why some people dislike Go. The Go authors have made a decision about the language and are sticking to it. I get the impression that they are doing this because they believe they are 'right'. That makes some people uncomfortable because we programmers like to discuss everything, and argue, and it's hard to come up against people who have what is close to 'faith' in their own beliefs.