7 ms·
I have a bit of a love-hate relationship going on with Go. On one hand, it addresses many of the pain points I've experienced with other languages. It's easy t
by matthewmacleod 11y ago
I have a bit of a love-hate relationship going on with Go.
On one hand, it addresses many of the pain points I've experienced with other languages. It's easy to build and deploy, reasonably performant, and has a powerful and consistent standard library.
On the other… developing in it feels like a total slog. It manages to be simultaneously far too anal and overly forgiving about syntax. Visibility definition using upper/lowercase is a shite idea. Package names (and packaging generally) are a mess. Magical built-in globals are a huge design smell. The lack of generics, as cliché a complaint as it is, results in loads of duplicated or generated code when building anything more complex than the simplest app. And so on.
I find the whole experience of using it to be unpleasant (rather like using a blunt knife), and yet it fits a set of requirements that mean I keep developing new projects using it – particularly high-performance small services that do things like fling JSON around, for which the built-in HTTP libraries + Gin are brilliant.
I'm looking forward to the point that a (trans|com)piler which smooths over the bad parts is available.
- arxpoetica 11y agoCoffeeScript for Go? ;)
- k__ 11y agoAfter using LiveScript I wished there was a transpiler for every language to get LiveScript syntax in there...
- beering 11y agoAgreed. All of Go's deficiencies are not deal breakers when it is so well suited to network services that shuffle data around. I wouldn't build lots of business logic in Go, but often I just need to proxy data from point A to point B with some data massaging.
- bkeroack 11y agoYou either "get" Go or you don't. Which shouldn't be surprising given that it is a very opinionated language. A diagnostic indicator is whether you gravitate towards things like Martini or Gin, which aren't idiomatic Go and seem designed to ease the pain of using Go for those who don't actually care for it much.
- lobster_johnson 11y agoBut it's possible to "get" Go and also disagree with its design decisions.
- spotman 11y agoCurious your opinion on what you would advise if not Martini or Gin? I love martini (and lately gin) and definitely love and use go every day. What about these frameworks is not idiomatic go? Is there another framework that is? Or you suggest just rolling your own using net/http by itself? Cheers
- kornish 11y agoHere's a great blog post by the author of Martini about why, after he had gained experience in Go, he came to realize that Martini isn't very idiomatic: https://codegangsta.io/blog/2014/05/19/my-thoughts-on-martini/ https://codegangsta.io/blog/2014/05/19/my-thoughts-on-martin... tl;dr - Martini doesn't have a strict, type-safe API. Overuse of reflection leads to a small performance loss but a much larger, much more important cognitive tax.
- jonesb6 11y agoI remember awhile ago Martini used to have a large performance hit that Gin didn't. I think it had something to do with the url multiplexer, wouldn't be surprised if it's since been fixed but it was the reason I initially chose Gin when I first started writing Go.
- elithrar 11y ago> I think it had something to do with the url multiplexer "Slow" in the case of a router/mux is entirely relative though. There's been this strange focus on routing speed/allocations, when its the smallest slice of your total request-to-response performance. Martini's router won't make your application noticeably slower than any other.
- Meekro 11y agoAfter a day of writing Go, I certainly gravitate towards martini and gin!
- lobster_johnson 11y agoI'm in the same boat. Go's simplicity is initially refreshing, then a huge pain once you find yourself writing the same thing over and over again. A good example is errors being values — which is a great idea. But then you realize every single function needs to be littered 1-10 cases of if err != nil { return nil, err } It's an extremely common pattern. It's tiring to write, over and over. Tiring to refactor, too: If you change a signature (to add an error, or add another return value, for example), every error check has to be updated. Unfortunately, Go doesn't offer any abstractions that might allow you to avoid such boilerplate. Functions that return errors cannot ever be chained, for example: If you have "func bar() (MyStruct, error)", you cannot do "foo(bar())". You must always assign the result to an intermediate variable. You could embed the error in the MyStruct struct instead, but that goes against Go's grain. I find myself wishing for some magic macro that is smart enough to extract a value and return the error for me. Something like: try! value, err := bar() ...would expand to: value, err := bar() if err != nil { return } I'm with you on upper/lower-case names. It results in schizophrenic-looking programs. Unless I'm writing a library, I tend to just export anything that isn't obviously an internal implementation detail, for consistency. I'm also up in arms about ":=" assignment behaviour. I've run into several bugs caused by shadowing inside blocks. You have to be careful when refactoring so as not to cause shadowing issues; really, editors should have their syntax highlighting set to highlight ":=" in blinking bright yellow or something. It's so hard to miss. It's also inconsistent with how you (or, at least, I) want it to behave. It will shadow existing variables by default if there is at least one new variable on the left-hand side, but that's the least conservative behaviour, and feels contrary to Go's strictness — a language, after all, that considers unused imports to be a compilation error. Recently I've started avoiding ":=" in favour of vars, just to avoid falling into that trap by accident. To be fair, I love many aspects of Go: Compilation speed, relative performance, ease of concurrency, static strictness. But after working with Go for a while and being quite productive with it, I'm at the same time seriously pining for a better language to replace it.
- plexicle 11y agoI'm not an expert in Go, but can't you inline a statement before the conditional? value, err := bar(); err { // there was an error } I like how that looks, personally. Obviously YMMV.
- codemac 11y ago> particularly high-performance small services that do things like fling JSON around :/ Their json system reflects and allocates like a mad-man. It's probably one of the slowest parts of the std library.
- lobster_johnson 11y agoDo you know of a faster JSON library? I've been struggling with this. My particular use case is that I don't want any fancy struct unmarshaling; I just want the equivalent of map[string]interface{}.
- nicksardo 11y agohttps://github.com/nicksardo/jsonpath https://github.com/nicksardo/jsonpath can pull out parts of a JSON document without unmarshalling.
- lobster_johnson 11y agoThat's really neat, thanks (do you have any benchmarks comparing it to Go's JSON?), but doesn't cover my use case. I want all the values in a map-like API. I don't know anything about the shape of the contents, names of the keys, etc.
- ptman 11y agoWhich libraries have you looked at? https://github.com/pquerna/ffjson https://github.com/pquerna/ffjson and https://github.com/benbjohnson/megajson https://github.com/benbjohnson/megajson claim to be faster
- lobster_johnson 11y agoLooked at both. ffjson is a library that generates the marshaling/unmarshaling Go code for your structs, so it doesn't support my use case at all. megajson is abandonware ("This tool is unmaintained. Please use ffjson instead"). go-codec [1] is very good, and can do things like interning string keys to reduce allocation overhead, but it's not faster than encoding/json when working on plain maps. [1] https://github.com/ugorji/go https://github.com/ugorji/go
- skybrian 11y agoI'm skeptical that "feels like a slog" has much to do with language features you complain about. Better IDE support would go a long way here. Java can be terribly verbose at times and the culture often makes it worse, but it often doesn't feel like a slog in practice because errors are reported as you type, with quick fixes. Editor plugins for Go will tell you some of the errors, some of the time.
- matthewmacleod 11y agoI'm not sure about that. I don't tend to use an IDE, but the Go plugins for Sublime seem to do a pretty good job of identifying unidiomatic code and errors even before saving, which is certainly a benefit. Gofmt is fabulous. The slog seems to be in the frequent feeling of 'why do I have to do this – surely the computer should be doing it for me?'. This is mostly around things like list comprehension, where it feels like using stone-age tools. It sucks, because the development story around e.g. goroutines and channels is so elegant in comparison.
- eluusive 11y agoYou really should check out vibed. It meets most of hte requirements of slinging JSON around, being easy to build and deploy, has a powerful and consistent library. And it's not terrible to work in: http://vibed.org http://vibed.org
- tptacek 11y agoIt's like most languages: if you go in hoping to write in the style of your favorite previous language, the language is going to resist you. Python does the same thing to you if you want to write in functional style. Ruby also punishes you if you want custom data structures (it's the Rails community that coined the term "golden path", right?). If you've got loads of duplicated code due to lack of generics, you may not be leaning as much on the design of the standard library as the language wants you to. We've got a limit-order-book market with a FIX API and an HTTPS/JSON API, a bunch of market makers, an AVR emulator, a dispatcher to handle thousands of AVRs concurrently, a C compiler, HTTPS/JSON APIs to implement debug stubs for all of that, and a bunch of other random stuff --- and we have one (1) custom data structure --- the red-black tree we use for the order books themselves. I'm a recovering C++ programmer and do not doubt for a moment that if Go had generics, I'd have availed myself of them. I'm not sure my code would be better for it, though.
- kasey_junk 11y agoYour code in Go almost certainly does use generics. Just not user defined ones. I don't particularly want to argue the generic point as I believe it is beat to death. But I could use a good concurrent map in Go in dozens if not hundreds of places. I could use a lock free ring buffer in dozens of places. I could use promise/futures in dozens of places. I could use anything but the big honking lock that is channels in dozens of places. I could use proper variance rules in the generics Go does provide in dozens of places. I could use monadic style errors and options in dozens of places. Now, I agree that I generally don't need to write my own generic code very often, but if the blessed generic writers on the go lang compiler team don't write these things for me, I don't have a fall back option in Go (other than code gen, which people are starting to fall back on). It just seems unsustainable to me.
- tptacek 11y agoThat's a fair point: the fact that Go seems to have a few hardcoded generics is one of the uglier bits of the language. I don't think Go is a great language, as I'm fond of saying, I just think it's a very useful tool.
- Sevzinn 11y agoPerhaps you are not smart enough.