11 ms·
Go Is a Shop-Built Jig
- sat 12y agoSeriously, in good faith, I attempted to learn and write a simple web application in go. I found it hard coming from a world where IDE support was available in other languages that do autocompletion and things like that and development just moves faster. In go, there is some level of support in sublime text, go for vim etc, but it is not nearly as full featured as say, IntelliJ. Want to learn about the javadoc - Command + J. Want to refactor code, much easier than in go. So tooling is a big problem I encountered. Next in line is lack of reusable data structures. Sure, embedding of structs is supported, but lets see...what will you do with a person struct (name, age, gender) that should be part of a employee struct and also the executive struct. You have 2 options 1) copy paste the person struct fields into each of the other structs or 2) you have interfaces and implementations of those interfaces so you can only deal with it through interfaces using embedded structs. What we really want is a flattened struct (just like inheritance). Most time people use inheritance not because its the right thing to do for that piece of functionality, but because it allows easily flattening out a data structure so you have reuse of a common data structure with common properties across other data structures. This one killed it for me with go. I can't reuse. I am not google to have loads of dollars and when I try to make things work, I need to be able to keep an eye out for bugs that can creep in with go where re-use is artificial or takes excessive work to get. All in all, maybe go has its niche, but for a small shop that runs on scanty resources and needs to build robust and reliable applications, a heavy weight like Java or .Net is still ruling the roost.
- campoy 12y ago"What we really want is a flattened struct" That's what we call struct embedding. Check this http://talks.golang.org/2014/go4java.slide#33 http://talks.golang.org/2014/go4java.slide#33 for more details.
- sat 12y agoEmbedding won't give you a flattened structure with transparency you expect. In other words struct B embedded in struct A will only create a syntactic sugar so that you can access properties of B through A. It won't work in other cases .Check this out - http://stackoverflow.com/questions/24333494/golang-reflection-on-embedded-structs http://stackoverflow.com/questions/24333494/golang-reflectio... This is not to say inheritance is better. I am just illustrating how reuse is harder with go because it expects a lot more code to do a simple thing.
- kasey_junk 12y agoThat's funny, because I'm also a Go skeptic but your 2 points are literally exactly the opposite of mine. On the top 2 of the things I like about Go they are tooling and removed inheritance. Being able to fire up a fully formed, non-handicapped environment consisting of only vim and some command line tools is great. I've tried repeatedly on the JVM to accomplish this and always end up back with bloated IntelliJ and the vim plugin as my only option. I would say that in the last 15 years I've used inheritance correctly a handful of times, embedded structs are nearly always the correct solution to data structure reuse problems. That Go prioritizes composition over inheritance for data structure reuse is one of its fundamental value propositions, that anyone that has used Java extensively thinks otherwise is baffling to me. If Go had a longer history I'd probably argue the exact opposite conclusion of you. If you are a small shop with scanty resources and need to build practical business solutions Go seems like a great choice. Conversely, if you are able to afford the best developers and have massive enterprise software needs, maybe Java or .Net makes more sense.
- sat 12y ago>> bloated IntelliJ and the vim plugin as my only option Bloated it may be but helps me get the job done faster...much faster than I can do it in vim. I work on a mac with 16 GB RAM and thats sufficient for lots of processes. Every bit of the way, I have documentation I can lookup right within as I type, I have autocomplete that always works, I have debugger support to catch little things I missed, tons of libraries and plugins that have stabilized over the years...whats not to like? The downsides (and the reason I looked at go) are both Java and .Net are memory hogs. I needed something more lighter that would offer the same level of productivity during development.
- kasey_junk 12y agoBut that's the beauty of the go tool chain. I have a source browser (godef), a documentation browser (godoc), a code style formatter (go fmt), code vetting (vet), unit testing (go test), a linter (golint) etc. and they are all fast command line programs. This means that it is trivial to setup a vim/command line environment the way I like. In my vim setup with simple key strokes, I can go to the source of, see the type definition of, see the documentation for the call under the cursor. I have formatting, vetting, and if you want compiling on save of the file (and it's super fast). I have autocomplete that behaves exactly as I want it to. I wish there was better ctags support for go, and the go oracle tool is more prototype than production software, but on the whole I am much happier with my development chain in go than I've ever been on the JVM or .NET.
- tagrun 12y agoAs you have discovered the hard way, trying to write Java in Go is not productive.
- mentat 12y agoHave you looked at this? http://howistart.org/posts/go/1 http://howistart.org/posts/go/1
- sat 12y agoStruct embedding is just syntactic sugar. Have you tried using reflection to look at the fields of the struct? You don't have a chance of looking that the embedded field properties as if they were truly embedded (flattened out as in inheritance) using reflection. Now put that opposite inheritance. No matter what you do (reflection, direct access what not), you still can get to those properties. See why I am saying go is making it harder? Its those cranny little details that you experience that drop your productivity.
- smegel 12y ago> a small shop that runs on scanty resources and needs to build robust and reliable applications, a heavy weight like Java or .Net is still ruling the roost. That seems to be the opposite usual scenario for "heavyweight" enterprise frameworks. I actually think Go hits the sweetspot - faster to develop in than Java/.NET, but much more robust, reliable and faster than the scripting languages.
- sat 12y agoHere is a competition. I'd write in Java and you can write in go. Lets crank out a simple ToDo CRUD application. Any bet who will finish faster? This is not to say go is bad at all. Its been designed by people 1000x smarter than me. But it isn't helping small shops go any faster or be more productive than they are with current setup. Talk about progress of the 21st century programming language...can't find much.
- smegel 12y ago> Lets crank out a simple ToDo CRUD application. Any bet who will finish faster? Well I haven't done much web programming in Go, so I would not be very fast. I have done a lot in Python, and I usually finish prototype apps within days while the Java teams are still stuck in meetings with the Oracle DBAs trying to work out why Hibernate is generating shitty SQL again. And I believe Go is comparable to Python as far as productivity is concerned, but with type-safety and speed. I think there is a lot to commend of Java, well at least the JVM, and the tooling and libraries are great, as is the performance. But I rarely hear anyone argue it is a fast, agile language to develop in.
- sat 12y agoWell, I was just comparing Java - a complied, strictly typed languages to another in the same domain - Go. Scripting and interpreted languages like python, ruby are a different thing altogether. I agree with you that ruby/rails or python/django get it done a lot faster. On the JVM, we get close but not quite - with Grails and Play. Spring Boot seems to be getting up there as well in terms of productivity. They still have some way to go.
- nl 12y agoI've tried Go some too. I disagree with your assessment of the data structures (inheritance isn't always great), but the tool thing I strongly agree with. I'd note that all the replies at this time argue the point about data structures, but none address the tooling. I want my autocompletetion, dammit! And I don't want to use Emacs or Vi to get it. The lack of refactoring support was what ended up making me switch back to Java+Dropwizard. I'm just much quicker at evolving services because of the better tooling.
- kristianp 12y agoThis piece reminded me of "Zen and the Art of Motorcycle Maintenance", with its talk of the practical qualities of the language through analogy to a shop-built gig.
- threeseed 12y agoWhat is with Go supporters ? I don't understand why if I don't use Go then I am not solving real world problems and instead building over engineered monstrosities. Working in the enterprise features like exceptions and generics makes it easier to ensure consistency across the platform and our 20+ developers.
- shadowmint 12y agocome on, thats a bit hyperbolic isnt it? There are plenty of go fanboys out there who will rage about go getting any kind of criticism, but this was a really thoughtful take on why go is a good practical language despite the problems.
- tagrun 12y ago> What is with Go supporters ? I don't understand why if I don't use Go then I am not solving real world problems and instead building over engineered monstrosities. What is with you? The article is talking about languages, not the category of problems people are trying to solve using those languages. (In principle, NASA could have written the Mars rover code in brainfuck). > enterprise features like exceptions and generics What is an "enterprise feature"? Sounds like a Java-world word though. I also don't understand how generics and exceptions "ensure consistency across the platform".
- oakwhiz 12y ago>What is an "enterprise feature"? I think what the grandparent poster meant to say was: >Working in the enterprise, features like exceptions and generics make it easier [...]
- threeseed 12y agoFrom the article: "Go feels under-engineered because it only solves real problems" "and so you build real solutions rather than finding excuses to use your beautiful tools" The implication from reading the article is that those of us that rely on those so called exotic features aren't doing so for serious business and technical reasons. And it seems to be a common thread amongst many Go users. And generics allow you to reuse existing components much cleaner and exceptions allow you to handle errors in a consistent way across the system. You can build error handling classes but often handling errors explicitly doesn't scale.
- fineline 12y agoBut you can't deploy your Go to iOS. Or your Swift to Linux. I'm getting interested in Nimrod (or Nim as I think it's planning to become). Compiles to native binaries via C, C++ or ObjectiveC. Even compiles to JavaScript. So it will run on all consumer and server platforms, on microcontrollers and in browser. And it has generics, exceptions, macros, inheritance, and (optional, time-boxed) garbage-collection. It's a tiny community which hasn't even managed to get a Wikipedia page to stay up, but I'm barracking for it.
- tagrun 12y ago> But you can't deploy your Go to iOS. And? iOS and Android supports are on their way in case you're not following recent developments. In case you're interested in writing programs for mobile devices, there's already a supporting go.mobile repository with (mainly targeting Android at the moment). > And it has generics, exceptions, macros, inheritance, and (optional, time-boxed) garbage-collection. Sigh... this "where's my feature!" argument almost always comes up. It is not reasonable to expect that feature X that is very important to you has to carry the same weight for other people. Some people think that it is unthinkable to write programs without feature X. If you think that way, then Go is probably not a language for you. Note however that there are many people who do not think that absence of feature X is a crippling thing, and do enjoy writing programs in Go. > It's a tiny community [...] in total contrast with... Nimrod community?
- wutbrodo 12y ago>> It's a tiny community > in total contrast with... Nimrod community? He _was_ referring to the Nimrod community here.
- pjmlp 12y ago> OS and Android supports are on their way in case you're not following recent developments. Yes, but it remains to be seen how Go's view on data structures map Objective-C and Java APIs. As for Android support, the Android team doesn't seem to care any little bit about it, given their statements on Google IO. So you have developers of a Google language trying to target a Google platform, where the platform owners just want to support Java (NDK is a kind of stepchild).
- lukasm 12y agoI would switch from python to Go but - Type system needs to be improved e.g. generic code - Verbosity, duplication of code are painful - Lack of functional features - Tooling - Maturity
- stock_toaster 12y agoTooling? I am not sure about that one. Go tooling is pretty nice. The one area lacking a bit is, for want of a better word, "package management". However, I have been using gpm with success, and others are happy with godep. For me, the biggest pain point is, to be honest, dealing with json. json in Go is not as fast as you would expect, due to the overhead of runtime reflection. Parsing "loose/dirty" json is also painful. If you cant be sure ahead of time if a value is `"1"` or `1` (int or string of int), and have to support both, you are going to have a bad time.
- sagichmal 12y ago> If you cant be sure ahead of time if a value is `"1"` or > `1` (int or string of int) ...then your data provider is _broken_ and you need to take it up with them :)
- stock_toaster 12y agoWell, these are B2B customers, who are huge companies. We have actually had customers say they can't even find which servers are running the code, so could we "pretty please with money on top" just make it work anyway.... Sometimes you actually have to deal with what you get, and can't just "fix the other end".
- RHSeeger 12y agoTo be fair, a favorite tagline of the Go community is "it solves real problems". Dirty JSON (with no simple way to fix it) is a real problem.
- zackbloom 12y agoIt might be a bit more painful, but it is totally doable. You could parse that field into a generic interface, and check the type in your code, or you could create an interface which requires an `AsInt` method, and implement it for both options. I personally struggled with the json parsing issue a fair bit, but persevering resulted in me having a mostly static typed setup which has ended up being much better than when I've used JS or Python.
- ANTSANTS 12y agoProps to whoever built this presentation software. With Javascript disabled, it gracefully degrades to a basic HTML page. Most others leave you with a single broken slide.
- dkarapetyan 12y agoNotice the author would still rather use Swift when he's doing fun stuff. I get this sentiment and more than once I've wished there were more constraints in the language to mitigate the damage some kid with a chip on their shoulder could do but it says something about the psychology of programmers, "I know personally I'm good enough to do magical, wizardly stuff with all the cool stuff that Swift gives me but you, well, you need some training wheels so we're gonna use Go for this project". I don't know about you but I'd rather work with people that understand the tools they are using and when it's OK to do fun stuff and when it is important to exercise restraint and "dumb it down" for the good of the team. Using the language to solve the problem of uneven programmer ability feels a bit off. It's something out of 1984. You can't say "great" in Go you can only say "good++".
- zackbloom 12y agoSo you're saying you want programming to be hard because that means you get to work with smarter people? I think what Go is striving for is simplicity, not elegance. And that change makes the code easier to write and maintain for everybody involved. At 10AM I might feel like writing Swift, but at 3AM I'm sure as hell glad I used Go. Or, less anecdotally, I maintain about twelve services in Go, including web services, proxies, and an analytics engine, and I have never been woken up in the middle of the night with a failure. That was certainly not true when I was writing Python or Javascript. Erlang or Swift might offer comparable reliability, but it comes at the cost of a lot of complexity.
- dkarapetyan 12y agoDefine what you mean by hard and then I can say whether you're correct or not. Otherwise you're putting words in my mouth. I didn't say I want programming to be "hard" but I did say I'd rather work with smarter people. That doesn't mean smarter programmers exclusively program in Haskell, Erlang, Clojure, Scheme, Racket, SmallTalk, etc. I find programming overall to be quite easy in any language once you're used to thinking with the abstractions the language offers. The hard part is communicating with other people. Also, your "less anecdotally" is by definition pretty anecdotal.
- 12y ago
- bascule 12y ago"Go feels under-engineered because it only solves real problems" This belies a multitude of real problems Go doesn't solve, like generics or preventing data races
- zackbloom 12y agoAs he said in the article, neither seem to be problems which come up in practice. I maintain about twelve Go services running in production, and neither failure has cost me any significant amount of time.
- the_af 12y agoWhat kills me is that generics (or any other programming language abstraction) are not problems, but problem-solving tools. Technically speaking, they are never needed, if your definition of "not needed" is "I can work without them". You don't need anything beyond assembly language, really. The thing with most tools and abstractions is that you don't appreciate them until you use them -- when you truly use them, not merely when you learn about them. Then you wonder how you ever lived without them. You don't know if failing to use an abstraction hasn't cost you a significant amount of time until you've embraced their use. To me, this is a variant of the Blub paradox at work.
- bascule 12y agoI constantly see users of Go running into these problems. If you haven't, good for you I suppose.
- enneff 12y agoGenerics are not a problem to be solved, they're a tool to solve problems.
- bascule 12y agoThe lack of generics is definitely a problem. You can't write generic code, and end up having to write your own thunks for each type you want to use. The standard library can't expose generic facilities that work on any type. This should be evidenced by the fact that Go is the only mainstream statically typed language without parametric polymorphism. Worse, trying to bolt it on after the fact has generally lead to ugly solutions, like C++ templates or Java's generics. I expect Go will eventually follow Java's lead and bolt on generics awkwardly.
- zenjzen 12y agoGo v.s. Swift's flatMap? Monoids v.s. non-monoids. Hard to compare the two.
- metafex 12y agoLack of generics seems to always be the argument against Go. I have been coding in Go for over a year now nearly every day and it really became an annoyance only once: CRUD operations in a web-service expecting JSON-objects. That's literally the only time where the code-duplication was a problem for me. Now, not everything else has been all good (mostly minor issues with community libs), but the one thing that never ceases to amaze me with go is that: You hammer out a few hundred lines of code, compile, fix those few syntax errors, compile again and 9 out of 10 times your code just works. The simplicity of the language is the key. It's a tool that feels right and gets the damn job done.
- spion 12y agoThe funny thing is that adding generics will also improve error handling as you would be able to make that Result<T> generic from Swift and implement flatMap for it. This would be as good as exceptions, if not better because its very explicit and can be made compatible with the existing mechanism. This is why I find it unbelieveable when Go users tell me "I never need generics". I look at their code and see if err = logit(FrobulatingMessage); err != nil { return err } repeated over and over again and can't help it but cringe
- metafex 12y agoYou get used to that pattern ;-) Also, the "I never need generics" made me smile. Sure, one can get by without them, but sometimes, as I said above, it would be really nice to have them.
- spion 12y agoGetting used to it is not the point. What I find cringe-worthy is that that's a bewildering amount of noise. It actually makes it harder to figure out what a specific piece of code does. Admittedly the error pattern is so common that I can imagine people getting very much used to it, but thats not the issue here. The problem is indicative of Go's lack of abstraction power, and its pervasive. There is no difference between `filter`, `map` and a regular foreach - every piece of code that wants to do things like that must re-implement the mechanics of creating new slices and assigning things to members which are accessed using a specific index. So many details - I can't see the forest from the trees! I see the same kind of noise in legacy messy projects where a piece of code works on multiple abstraction levels and its impossible to think about what a it does without thinking about the mechanics of how it does it. Given all this I really can't understand how someone can call Go code beautiful and clean. My gut reaction is "this will cause a mess couple of years down the line". The cost of not having generics in Go is really understated, and it saddens me greatly. With them, Go would be an extremely interesting language. But apparently, the language designers believe that you (the user) are not to be trusted with writing sensible abstractions and therefore are forbidden to do it.
- mononcqc 12y agoThe few things that bother me about this article are these apparent contradictions: > And then, when it was all working, I refactored out the duplicated code. And I refactored again. And in the end, the whole thing was simpler and shorter than what I would have done with generics And then: > When writing the Go function, I started at the top and typed until I got to the bottom. And that was it. There aren’t very many ways to write this function in Go. You don’t need generics, just refactor until it works; also, you don’t really need to think about how to rewrite thing, it should be obvious. Other bits, like: > So again, in the end, Go turned out to be a language for solving real problems rather than a language filled with beautiful tools, and so you build real solutions rather than finding excuses to use your beautiful tools. […] But if you’re trying to solve specific, practical problems in the forms professional developers typically encounter, Go is quite nice. Seem to carry the implicit assumption that it’s a mutually exclusive problem, or that having beautiful tools leads to not solving the problem appropriately. That if you use fancy tools, the problem somehow doesn’t get fixed, masturbatory practices take place instead. I’m not sure I can see myself agreeing.
- chvid 12y agoAm I the only one who is very confused by these examples? A function named "frobulate" - what is frobulate? I dunno. The function calls: thingsToFrobulate, logit, cleanupOldest, processOld, doNewThing, cleanup and somehow FrobulatingMessage is set on the way. Honestly; you can do the most clever functional programming in the world but if you naming is like this then your code is just going to be bananas. And BTW: both Swift and Go are missing exceptions; I think those would be very helpful here.
- sj4nz 12y agofrob is a https://en.wikipedia.org/wiki/Metasyntactic_variable https://en.wikipedia.org/wiki/Metasyntactic_variable , but not a "common one" which may have led to your confusion.
- chvid 12y agoOk. Maybe I am not getting the joke then. So thingsToFrobulate, logit, cleanupOldest, processOld, doNewThing, cleanup and FrobulatingMessage are "metasyntactic variables" too?
- sj4nz 12y agoIt just comes down to a habit of giving a name to something as an example of something that isn't meant to map to any problem domain. E.g. when a manufacturer is in the business of making "widgets," we know they're not actually making products that are widgets (whatever those are.) Once you know that the names being used are not considered to be "important", the other names aren't as important as well, only the syntax. These metasyntactic variables are useful for avoiding situations like "Who's on First?" (e.g. https://www.youtube.com/watch?v=kTcRRaXV-fg https://www.youtube.com/watch?v=kTcRRaXV-fg ) which is humorous to native-English speakers, but probably incoherent to non-native English speakers.