19 ms·
Problems with Go's design
- qihqi 11y agoGo is inspired by the C++ subset that Google choose to use (Just look for the Google's C++ style guide to look for things that Google banned). So in many ways, it's chosen to work as C++ in lots of corner cases. In fact, that enabled automatic tool to convert Go compiler written in Google's C++ to Go.
- aikah 11y ago> In fact, that enabled automatic tool to convert Go compiler written in Google's C++ to Go. Hmm, I thought go was written in C at first place and not C++. It seems to me that Go creators were never big fan of C++ so I don't think it takes any inspiration from C++ . All I see in some kind of C + garbage collection + interfaces and some concurrency percs. I fail to see how it was influenced by C++ in any ways.
- mbrubeck 11y agoThat's correct, the Go toolchain was originally written in C, and translated from C to Go: https://golang.org/doc/go1.5#c https://golang.org/doc/go1.5#c And of course Go's designers include some of the designers of C (well, its predecessor B) and Limbo, and Go seems influenced more by that tradition than by C++.
- Jemaclus 11y agoNailed it. I love Go, but all of the things listed in this article (and more) make me bash my head against the wall more often than I'd like to admit. That said, there are some fantastic things about Go that aren't listed in the article (I feel like gofmt changed my life). Don't let this article discourage you from investigating Go as a tool to use!
- kodablah 11y agoSame here. Mark me down for loving the runtime/community and having issues with the language. Someone's going to target the Go runtime w/ a better language and zero-overhead and I'll be happy. I can't just switch to Nim or D because I still want the Go ecosystem (e.g. /x/crypto/ssh).
- spion 11y agoI've never understood this, every Go user swears on gofmt for some reason that I just dont get. Can you elaborate how gofmt changed your life? Its a really simple tool and lots of languages have those...
- Jemaclus 11y agoYou're right. There are other tools out there. But what I really appreciate about gofmt are a few things: * It's highly opinionated. It's not cluttered with customization options. This means your Go program and my Go program are formatted exactly the same. Period. I don't have to choose between spaces or tabs or get annoyed that you chose spaces when tabs are clearly superior. * By being highly opinionated, Gofmt just takes care of those decisions. You focus 100% on coding -- not on stylistic decisions. * It's practically built in and maintained by the core team. The "other tools" out there are usually open-source. You have to go hunting for them. Gofmt ships right with Go. Then you have to figure out how to run them. With go, it's just a simple `gofmt <file>`. Boom. Done. No NPM dependencies, no Ruby gems to install. Just run it and move on. I don't write Go full-time, but I've started adopting similar tools for my primary languages. My editor at my current job runs a similar tool for Node. I don't have to think about style any more. It's just taken care of for me. And all of my team have reached the same conclusion. Peace of mind and focus on what really matters is invaluable.
- spion 11y agoThe reason I don't get it, I think is that I've never cared about stylistic decisions, ever. Why would anyone care, I have no idea. I can configure my editor for either spaces or tabs. I run npm install when starting with the project anyway, and it will also fetch any devDependencies for me (which means a script such as npm run stylecheck can be made available). The project lead decides the rules. Or there can be no style rules, it doesn't matter - most of those are very superficial and have little to no effect on anything.
- mikestew 11y ago"Alright, the title is quite bold, I admit it. I’ll tell you more: I love bold titles, they are all about attention." In other words, click-bait. Oh, you think I use the term lightly? For an article that boils down to "things about Go that aren't particularly wrong, but I don't like", the author concludes with "I hate the language: it’s absolute crap". Really? Because when you throw the kitchen sink into your imports "just in case", it won't compile? (I pick on this particular example because dragging along imports you're not even using just strikes me as sloppy, hence coloring my view of the author.) It's one thing to state, "I would have done this differently for these reasons", but to call the whole bundle "absolute crap" just reeks of some n00b who learned a single dynamic language, switched to Go, and had a hard time figuring out why his crap code wouldn't compile.
- aikah 11y agoPoint 4 makes sense though , it would really help with polymorphism in Go ,without generics. This is the kind of subtle behavior that is upsetting at times and I really think this is where the language could improve, definitely.
- bobbyrullo 11y agoFor every "quirk" mentioned in this article there are very good reasons for it, which the author lacks the imagination or patience to try and reason through. Point 4 is perhaps the best example. So given an interface Foo and a struct FooImpl which implements Foo, why can't we pass a slice of []FooImpls to []Foo? It's because the creators of Go are lazy and arrogant and incompetent and don't care right? No. Consider the situation where a []FooImpl is passed to a function F(f []Foo). This function decides to change one of the elements of the slice to a different implementation, say FooImpl2, eg. f[0] = FooImpl2{}. Now the original slice of []FooImpl's has a FooImpl2 in it. Oops, we broke type safety. Now consider what it would take to make this work - you'd have to somehow guarantee that functions which take []Foo don't mutate the slice. Is that possible? Is it possible to do quickly, and still have a language that compiles very quickly? Or we could introduce "const" and all those things from C++ but that's a whole new level of complexity to the language. And what about the performance penalties? A struct is a different size than an interface, so what code is emitted during compilation, something that can handle iterating over []your_interface and []your_struct? So next time you think "Gosh, this bit of Go really sucks" take a moment and think about why it was designed that way. Because the fact is, it was almost definitely designed that way, as opposed to just overlooked or neglected. You may not agree with the choice that was made, but with the people who work on Go, I can guarantee that there was a conscious choice that was agonized over and discussed endlessly, just not with you in the room.
- cs702 11y agoWhile the title is linkbait-ish, the article makes interesting points with code examples, and the author is not 'religious' -- he concludes by saying he will continue to use Go. Like most other languages, Go is neither great nor bad; it's just another tool designed by people to solve a specific set of problems -- in Go's case, people who in the past have had to develop very, very large, complicated systems with lots of concurrency. For projects like that, Go would be a great choice; for other projects, it might not be. In some circumstances even Ruby can be a better choice than Go for high concurrency. I recently read a post on HN in which the author (someone with an Erlang background) lays the reasons why he chose Ruby for a highly concurrent application. When I first saw the link, my immediate thought was, Ruby!!?? But then I read the post and the reasons were all very sensible and practical-minded, so in that case Ruby was arguably a much better choice than Go, Erlang, Scala, Rust, and the like. Here's the post: https://news.ycombinator.com/item?id=10394450 https://news.ycombinator.com/item?id=10394450 (direct link: https://github.com/rustyio/super-imap#why-ruby https://github.com/rustyio/super-imap#why-ruby) -- I really liked the rational, practical, 'non-religious' tone. Suggestion: don't call Go or any other popular language "poorly designed" with a short blog post. Instead, say "it doesn't fit my current needs."
- RodericDay 11y ago> don't call Go or any other popular language "poorly designed" with a short blog post. Instead, say "it doesn't fit my current needs." that's not what the author wanted to say though. very, very often someone says "this is bad" when they actually mean "this doesn't fit me". in this scenario, I think the author made a very good case for "it's poorly designed".
- cs702 11y agoRodericDay: Language design decisions by superstars like Robert Griesemer, Rob Pike, and Ken Thompson (the creators of Go) that may seem inconvenient or annoying when working on small to mid-size projects could very well make life much easier when working on giant projects which take years and do not fit on any single person's head. I'm reminded of this insight by Lawrence Kesteloot of Dreamworks: "What’s particularly hard is having technical discussions with someone who hasn’t broken through as many walls as you have. Breaking through these walls means making different trade-offs, and specifically it means making a decision that seems to make less sense in the short term but will help later. This is a hard argument to make—the short term advantages are immediately demonstrable, but I can’t convince anyone that a year from now someone may make an innocent change that breaks this code."[1] Unless you personally have led Internet-scale mission-critical software projects at a place like Google, as the authors of Go have, I don't think you're in a position to judge their decisions too harshly. Neither am I, BTW. -- [1] http://www.teamten.com/lawrence/writings/norris-numbers.html http://www.teamten.com/lawrence/writings/norris-numbers.html
- nteon 11y ago"I still wonder why we can omit commas on import/var/const blocks and just can’t on lists and maps. Anyway, Rob Pike knows better than me! Viva la Readability!" import/var/const blocks rely on semicolon insertion rules, list and map literals have a list of Elements separated by ',' [0]. I guess on the surface level I see how this is sort of inconsistent. It would be interesting to think about applying semicolon insertion to comma insertion. 0 - https://golang.org/ref/spec#Composite_literals https://golang.org/ref/spec#Composite_literals
- thorn 11y agoI think author of this article is strangely biased towards dynamic languages. Go is not about shortest programs in the worlds, yes sometimes code is longer than in python. But in Go I can manage code execution and predict memory easier better than in Python or other dynamic languages. Many things in Go were done on purpose. Learn to use Go and it's awesome tools, like gofmt, goimports and others.
- fixermark 11y agoI love Python, up until I remember that I can't make any guarantees of program correctness until I have 100% coverage tests on every line of code because the language is so flexible that it can't tell if a random identifier refers to a variable name that might exist at runtime (but is not determinable to exist at compile time), and therefore most of my variable-name typos that would be compile-time errors in another language are runtime errors in Python. So great for prototyping, not so great for large projects and maintenance (as I've just put the floor of my unit test cost around a factor-of-2 more code).
- TeeWEE 11y agoIndeed, with python i can program fastest, but whenever something gets big you had wished i programmed it in golang. However, its still a valid choice to choose python initially. It depends
- pcwalton 11y agoMany of the issues here--for example, the set of built-in slice primitives being inadequate--have ready solutions in other statically typed languages (in this case, generics). These are not problems fundamental to static typing. (For the record, I disagree with some of the criticisms here, for example the slice-of-interfaces type coercion criticism.)
- xemdetia 11y agoI agree strongly with this, it seems like the author has some expectations from his known language pool. Reason #3 about lexical scoping is the big one to me, as you can (and might want to) arbitrarily block variable scopes in many languages. The other components seem to be mostly that Go is still in flux as a language so things that are silly today may be fixed tomorrow, but that's kind of a built in expectation with the ability to transform source files to current. This feels like a lot of the early Java issues that were resolved some time later.
- elcct 11y agoThat's just part of the deal. Sometimes you just have to write few more lines of code. Your fingers won't die from it.
- deleted 11y ago[deleted]
- px1999 11y agoI guess I'm a "a pussy, 9-year old boy or afraid of little bit “strong” writing.", because as soon as I saw that sentence I lost all interest in finishing the post (though it was pretty linkbaitey in the bit I did read so I had marginal interest in the first place). Shit like that is why we have gender problems in the industry.
- dang 11y agoWe replaced the baity title with something more neutral, in keeping with the HN guidelines: https://news.ycombinator.com/newsguidelines.html https://news.ycombinator.com/newsguidelines.html
- boulos 11y agoOn a related note, unfortunately the system encourages attention grabbing headlines to make it to the first page. I think it's great that you then replace them, but without a penalty I don't think this will stop. Would it be hard to deduct say min(5, upvotes)
- dang 11y agoThat's indeed a weakness of the system, but it's complicated by the articles sometimes being good despite the clickbait. This is especially so with the publications large enough to employ specialist headline writers who put bait on everything.
- kzhahou 11y agoDang, I think you're too aggressive with article renames. The author claims that Go is poorly designed. And that's the title of the article. Yes, it's a provocative opinion (and the article text is loud), but the title itself was not outrageous hyperbole. I disagree with other commenters here: just because a controversial opinion will (naturally) gather more clicks, doesn't mean it's linkbait. The articles here on HN also surface on reddit and other forums. I frequently click links on HN just to discover I'd read them already. The title often contains a clue as to what I'll find in the article. The author presumably gave it some thought. When HN editorializes titles, I lose that context before I decide to click.
- dang 11y agoYou may not think this was linkbait, but I guarantee you that if this article were on HN's front page with that title, the thread would become about the title. All you need to do is look at the comments that were posted before we changed it. Your objection is really to HN's title policy. In my view that policy is a critical aspect of this site—indeed the longer I work on HN the more critical it seems. So I have to disappoint you here; it's not going to change. Huge numbers of HN readers would be up in arms if it did, even though no reader agrees with every particular edit moderators do.
- oconnor663 11y agoI would add "non-pointer method receivers allow you to modify the receiver object, but silently drop those modifications when the method exits (because they happen on a copy)". This is similar to the variable shadowing example in the article, in the behavior is the same in C and so kind of makes sense for that reason. However in both cases, Go's syntax makes it very difficult to spot the error (already-declared variables allowed to the left of :=, method calls implicitly taking a pointer to the receiver), where in C it would be more obvious.
- YZF 11y agoI actually had a subtle bug caused by variable shadowing. The current behaviour of := is error prone and IMO should be revisited. The situations where it cleans things up are offset by situations where it doesn't work (including in compound statements where it often ends up being I'd like to declare and check err but I also want to be able to use the other variable if err==nil). Another thing not mentioned is type switches, that feels like something that was duct taped onto the language. I think it would have been better to be able to use .(type) anywhere (e.g. in an if statement) and not have some sort of special switch statement. So make types more of a first class thing. It's obviously more work though but there is probably some middle-ground there that would make it seem less like a hack. I think the behaviour of slices is reasonable given that they are not as high level as they are in some other languages. They're basically a slightly nicer facade over pointer arithmetic and they are designed for efficiency and performance. I think overall they're fine. The "..." is a little awkward (appends could be a little nicer). Just use goimports to and you won't see unused import errors any more. Works for me and makes things cleaner. All in all I think there are some rough corners that could use a little polish but that can still happen, it's a new language after all. It's good enough to be really useful.
- Animats 11y agoYes, the semantics of ":=" for the multiple-variable case are just weird. You can create one variable and assign another, and it's invisible what's happening. Not too good. Variable shadowing is probably a misfeature anyway. If shadowing were an error, sometimes you'd have to change a local variable name. No big deal. An amusing alternative would be to require that any name imported into a block must be at least 3 or 4 characters long. You don't want short global variable names anyway; if "x" is a global variable, something is wrong. Then short local variable names could never clash.
- echlebek 11y agoThe behaviour you are talking about isn't anything to do with :=. It's just how scoping works in Go. := is just syntactic sugar. http://play.golang.org/p/bh6pm_8s9S http://play.golang.org/p/bh6pm_8s9S
- shawnps 11y agoI'm surprised to see the author mention not being able to compile when there are unused imports. Editor plugins that call goimports have solved this problem for a long time now. For example, I use vim-go (https://github.com/fatih/vim-go https://github.com/fatih/vim-go), and if I remove the only line of code that references the "fmt" package, the "fmt" import line at the top of the file will automatically be removed. Edit: Here is the reasoning on the FAQ behind code with unused imports not compiling: https://golang.org/doc/faq#unused_variables_and_imports https://golang.org/doc/faq#unused_variables_and_imports
- misiti3780 11y agoCool package, but it looks like it doesnt exist for TextMate
- yokohummer7 11y agoThis is a typical instance of solving language issues with excessive tooling. I find it uneasy that we will be reproducing all the baggage Java required us in a different language. And even Java didn't have mandatory imports.
- shawnps 11y agoI personally wouldn't call it excessive. It's more like set it once and forget about it. And it's something that basically all professional Go developers do, along the same lines of how everyone runs gofmt.
- JustSomeNobody 11y agoI wish the author would have taken a little more time to polish this and be a little more respectful.
- Jabbles 11y agoMeh. 1. How often do you insert into a slice? You know that's a O(n) operation, right? 2. nil is typed, I'll grant that it's not the most obvious part of Go's type system. 3. Meh. 4. This is type covariance. It's complicated and hard to get right. The Java Generics FAQ looks like this: http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.ht... 5. I like by-value loops. Everything else in Go is by-value. 6. Yeah, fuck everything we know about parsing, let's make whitespace significant, then we can declare slices like: x := []int{ 1 -2 +3 } len(x) == 3 y := []int{1 -2 +3} len(y) == 1 7. Meh
- pcwalton 11y agoThat's not type covariance. Variance only comes up when you have generics, which Go doesn't, and subtyping, which Go doesn't really have. It's the lack of a coercion/conversion between slice-of-T to slice-of-interface. The correct language-level solution to #4 is to introduce generics and to allow generic type parameters to have interface bounds. That would solve the problem without having to introduce variance.
- mpu 11y agoIsn't it possible to talk about variance as soon as you have a type constructor (function from types to types)? In this case []. Edit: I don't know go, but if slices give write access, I think the automatic conversion the author wants would be unsound.
- pcwalton 11y agoYes, a coercion would be unsound (at least, unless the coercion copied the backing store of the slice, which would be very unintuitive). It shouldn't coerce. I'm describing generic type parameter bounds, which are not the same thing. (For what it's worth, I'm not sure I would bother solving this problem if I were suddenly put in charge of Go's design, given Go's extreme aversion to type system features. I'm just describing what the solution to this problem typically is.)
- 11y ago
- Kiro 11y agoI don't understand 3. How else is it supposed to work?
- pbnjay 11y agoWhile Go could probably be better at not letting you shoot yourself in the foot, 1-4 seem to be code smells - you should fix your code and not the language. 5-6 seem to be personal preference, I have no problem with either as they are and they certainly don't trip me up. #7 as the author says himself: > noone actually cares, it’s just fine
- smegel 11y ago> it’s not foreach from C++. Ah the penny drops. We have a whiny C++ programmer on our hands.
- soroso 11y agoFUD
- strictfp 11y agoI've been bitten by #5 quite bad. Ranged over N elements in my slice, took the addresses of the values, copied to new slice. Ended up with a slice with N identical values. !?!?!? Took me about 30 mins of staring, printfing and whatnot before I understood what was going on (the loop variable containing the copies is mutable so you end up with pointers to it throughout the whole new slice. And at the end the value of it is the last element in the range. So I saw N*the last element when printing the result).
- TeeWEE 11y agoI worked on a project with go, and initially i liked it. Because the new way of thinking, and the fast compiler. But both the error checking, missing of generics, and missing of real functional programming paradigmas, required me to write something very simple in a complex way. I concluded that a simple webapp, is better written in python, and go was not the way togo for my project. In python you can quickly generate json from objects (yeah you can in go but only with ugly string comments). All in all, go has its place, but when you start a new startup, watch out with go initially.
- ericfrederich 11y agoAll these languages, Go, C++11/14, trying to be as concise as Python. Just look at those slice examples. At least C++ is playing catch-up. With Go there is no reason it had to be worse than Python right out the gate. https://gist.github.com/ericfrederich/c8d8513b9790106d87b7 https://gist.github.com/ericfrederich/c8d8513b9790106d87b7
- rtz12 11y agoYes, Go sucks. But currently, at least for me, I think it sucks a lot less than alternatives. No language is perfect, neither is Go. The most annoying thing is compiler instructions with special formatted comments. And Rob Pike calls that "elegant design".
- Artemis2 11y agoI think the author is a victim of the fallacy that Go looks simple, even though it's a very low-level language (think C without the quirks). Most of the — very valid — points they make are a consequence of Go not hiding complexity from the programer.