8 ms·
I played around with Go a while ago, and while I appreciated the approach to concurrency, I was really put off by both the boilerplate + how primitive the type
by piazz 6y ago
I played around with Go a while ago, and while I appreciated the approach to concurrency, I was really put off by both the boilerplate + how primitive the type system felt. Not having map and filter due to lack of generics meant writing for loops all over the place just to filter and modify arrays. Appending elements to slices felt clumsy. The type system didn't feel expressive, and I often found myself having to resort to the empty interface escape hatch.
Compare this with Typescript (or Swift, or Rust), which have type systems capable of modeling nearly any problem domain. Go doesn't have algebraic data types (sum types) which are incredibly useful in my experience (Swift/Rust enums, Typescript discriminated unions). I'm honestly not sure why I would use Go over TS, unless performance was my primary consideration. It feels like Go was designing to be as inoffensive as possible to a legion of new-grad Google programmers, and you sacrifice most modern language niceties for it. Please convince me I'm wrong, because I really wanted to like Go.
- Mr_T_ 6y agoYou'll be happy with the latest developments: https://blog.golang.org/generics-next-step https://blog.golang.org/generics-next-step
- erokar 6y agoI share much of the sentiment. I like the simplicity of Go, but I think they took it too far an ended up with something too dumbed down and lacking in abstractions and expressive power. It feels like a step backwards coming from other contemporary and popular languages like JS/TS, Python, Kotlin, C#.
- throwaway894345 6y agoI agree with this, but I suspect I disagree on the extent to which this is a problem. These things are minor annoyances in my opinion compared to concerns that are largely apart from the actual language itself, such as performance, ecosystem, tooling, deployment story, learning curve, etc. With respect to Python and JS, you can always drop down to `interface{}` for similar expressive power and type safety, but generally people don't do this for the sake of simple for-loop boilerplate. Here are some serious pitfalls with Python (it's the language I know best) that dwarf concerns about language features. JS, Kotlin, and C# share some of these problems. Go doesn't really share any of these problems; it competes well with JVM and .Net with respect to performance, and its tooling story is simply top-notch on the whole (of course, there are individual tool categories where other languages have better offerings). * Python is a super slow language and the proverbial advice "just rewrite the hotpath [with multiprocessing / with C / with Pandas / etc]" falls over for any bottleneck that involves processing a large object graph. In these cases, you can't use multiprocessing because the de/serialization and IPC costs will typically exceed any parallelism gains. You can't use Pandas because the data set isn't matrix-shaped, and even if you can shoehorn it into a dataframe, you'll end up calling back and forth between Python and Pandas/C so much that you'll lose anything you gain from Pandas (and have much harder to maintain code). Similarly with "rewrite it in C/Rust/etc", you'll have to basically rewrite the whole object graph (including all of the inherent classes and methods) into C/Rust/etc and you probably don't want to keep those in sync with the original Python classes, so congratulations, a huge amount of your code is now in C/Rust/etc and you're no longer enjoying any of the benefits you would enjoy with Python (probably iteration velocity). Sadly, performance isn't likely to get better in Python because the community is so heavily invested in C-extensions (because Python is so slow) and the C-extension interface is basically the whole CPython interpreter, such that anything that wants to play in the ecosystem has to be very CPython shaped including many mechanisms that are prohibitively difficult to optimize around. Pypy is making a lot of interesting progress, but compatibility is still a blocker for lots of applications (e.g., anything that wants to talk to a Postgres database--unsupported packages notwithstanding). Python is fine if all you're doing is shelling out to a database or a C library, but anything more becomes expensive quickly ("well how come $BIGCOMPANY is so successful despite using Python?!": probably deep pockets). * When you want to distribute a Python program (e.g,. an internal tool), your options are pretty limited--the executable zip file formats (e.g., PEX files) are pretty nice, but inevitably something depends on an .so file (because Python utterly depends on C for just about everything) that doesn't get included in the zip file. Even in the happy path, you have to have the right version of a Python interpreter installed on the target system. * Correctness is the least of problems with untyped Python or JS, rather the biggest problem is the lack of quality documentation (critical information is typically either missing or outdated). The second biggest problem is that there aren't rails to guide mediocre developers toward sane code--developers tend to not know how to "think in types" and the code is typically far more complex than equivalent typed languages as a consequence. * Python nominally has a static type checker, but it's still very immature (still can't model JSON or even callbacks with keyword arguments). Further, getting it to find the type stubs for a given package is an exercise in frustration and terrible error messages. The only hope is that the Python community seems to be leaning into type annotations, so that should drive improvements in tooling in time (how long? is a different question) * Tests are super slow, largely because Python is super slow. CI bills can get to be really expensive. Not a big deal for well-endowed companies, but this is really hard for companies with meager budgets (this is ultimately true for Python generally IMO, not just WRT CI bills). * Documentation generation is brutal. Developers have to document types and keep them up to date. Consequently documented types are never up to date and many libraries--even the most popular--just punt on documenting types altogether. Then you have to write and maintain your own CI jobs for building and publishing documentation packages. And the documentation is still really reader-hostile on account of the everything-on-one-page, nested-with-no-context structure (e.g., SQLAlchemy has lots of methods and even classes with the same names but minor variances in module path and the only way to tell what you're looking at is to gradually scroll up to the previous `class Foo:` block and then back down to the thing you're looking at. Good luck ctrl+f-ing around). The latter problem would be easily remedied within Sphinx. The typing problem will get better as the typing story improves, but it's improving at only a snail's pace (mypy is still prohibitively difficult and restrictive for many projects). Further, if someone wanted to build a godoc.org clone for Python that automatically discovered, built, and published Python packages, I don't know if it would be possible because Python doesn't have a standard repository structure. * Then there's a long tail of paper cuts. Black (Python formatter) is a welcome relief but it's also really slow. No decent editor plugins (dynamic typing) and PyCharm is relatively expensive and there's still constant friction between it and your preferred editor even after you've learned it. Python has no dead-code elimination so artifacts are frequently enormous--like "too big to fit into a lambda, better use an ECS task and good luck with those startup times" big. Etc etc.
- saagarjha 6y agoPython also actively hates functional programming and certain other language features that it "has", plus its standard library is extensive but also all over the place.
- forsakenharmony 6y ago> its tooling story is simply top-notch on the whole (of course, there are individual tool categories where other languages have better offerings). Personally feel like rust is better overall, but I don't know if you've tried it
- throwaway894345 6y agoI have, and I generally agree. Rust’s tooling is fantastic. Compiler needs a speed up, but impressive work all around. Would like to be able to use it more often.
- geodel 6y agoNo need to convince. If you've got something working nicely why would e.g. I spend my energy to convince you otherwise.
- skywhopper 6y agoThis sort of comment is not really relevant to the article that was posted, which is not about Go's type system, or convincing TypeScript users to switch to Go. I'm sorry that you don't like Go's types, but I'm going to guess it's not really targeted at your needs if you are a TS user. It's okay not to use Go for your projects. But there's no need to drop your personal opinion of a language into a post about specific case studies of how that language is used inside a company.
- piazz 6y agoOther comments on this post: > I absolutely love using Go. The logical flows for my programs... > Go is super productive. My day-to-day responsibilities include... > Nothing gets out of the way better than Go. > Go as a new language is a mega success. I'm guessing you're OK with these, and maybe it's just negative opinions that are irrelevant?
- yencabulator 6y agoIt's pretty much guaranteed there can't be anything posted about Go without that predictable comment on how bad it is. It's very repetitive, and hence annoying and not adding value.
- azakai 6y agoI'm not the person you're responding to, but I think there is a difference between positive and negative posts in this context. Negativity is inherently bad. There is a place for it, of course, but when it's off-topic it's especially unwelcome in my opinion. And programming language discussion already has far too much negativity.
- ahelwer 6y agoMany people find the "pozzy vibes only" philosophy much more annoying than relentless cynicism, which can at least be refuted by just ignoring it & building stuff.
- 6y ago
- mjevans 6y agoThe use of an Interface type in Go is a good sign that either the data or the logic flow isn't optimized for static analysis and optimizations. The most common case I happen to have run across is the result of parsing data or configuration files; situations where there might be structure, but all of it is optional. PS: Your "algebraic data types / sum types" sounds very much like interface composition, a ReaderWriter ( E.G. https://golang.org/pkg/io/#ReadWriter https://golang.org/pkg/io/#ReadWriter ) for example composes interface types.
- c-cube 6y agoThis is a product, not a sum. It's just a pair of Reader and Writer. Sum types would also give you the ability to say "reader or writer" and use pattern matching to find out which one you were given. C-like languages traditionally give only the 'product' half of types (C also gives union but they're super low level, and Go just eschewed them). A _modern_ language would give both products and sums.
- pkolaczk 6y agoInterface composition is product of types, not sum.
- bengalister 6y agoI still find the Typescript compilation time to be annoying. I rediscovered using Typescript for backend development on NodeJs and was very unpleasantly surprised by the compilation time (my only complaint). For a project with 20-30 files and around 8 dependencies, it took 10-20 seconds to compile and 4Gb of RAM (yes I checked with tsc --listFiles that no other files were parsed). The same in Go to compile to native would probably take <5s in my experience!
- piazz 6y agoSuper agree. Speedy compilation time of Go was my favorite feature. TS compilation is frustratingly heavy.
- smt88 6y ago> or a project with 20-30 files and around 8 dependencies, it took 10-20 seconds to compile Something is very wrong here. If you use `tsc -w`, you should get incremental compilation. Small changes should compile almost instantly. For me, even without using `-w` on pretty large projects, my compile time is never more than 5s. I have to wonder if you have bottlenecks elsewhere. Regardless, TypeScript's type system is much, much more expressive than Go's, so compile time will theoretically be slower. For me, it's worth it because compile time is an inexpensive way to save lots of maintenance time in the future. (Note that I would never use TypeScript and Go for the same type of project, but that's my mindset in theory.)
- qaq 6y agoTypeScript has way more advanced type system so there is a price you pay for that.
- pm90 6y agoIIUC, this is specifically a problem with the TS build system/runtime, not because it’s typed. Deno is attempting to solve that.
- Xavdidtheshadow 6y agoThat's a fair complaint, but I find that during development, I use `tsc --watch`, which makes incremental compilation very fast. Of course, that doesn't affect the slow production build time, but I care a lot less about that (since it usually happens off in CI land somewhere and I'm not sitting waiting for it to happen. So ultimately, this is a non-issue for me.
- yandrypozo 6y agothe key is simplicity, you're complaining about language features that allow you to write "fun" code, but remember that we spend around 80% of the time reading or debugging code, the main focus of Go is about writing code that's easy to read which will allow you to scale a project or source code with more people, also remember that easy doesn't mean simple, I think these 2 talks will make you understand my idea a little bit better: https://www.youtube.com/watch?v=rFejpH_tAHM https://www.youtube.com/watch?v=rFejpH_tAHM https://www.youtube.com/watch?v=2y0pmRJNkLA https://www.youtube.com/watch?v=2y0pmRJNkLA
- kevinmgranger 6y agomap/filter and sum types are not about "fun", they're about correctness and expressiveness. map/filter and their equivalent loops are both perfectly readable, but the latter involves more boilerplate.
- hrez 6y agoI'd settle for comprehensions. It already has generic for/range so why not. That would cover a lot of boilerplate annoyances.
- somethingwitty1 6y agoAnd I'd disagree. Numerous engineers of differing skill levels (what I deal with day to day), struggle significantly when map/filter are added into the mix. And we may say "get better engineers", but we don't have that ability. We have to write code that is maintainable for the engineers we have and can get (and the ones coming in the future).
- Guthur 6y agoCome on, map and filter difficult? That's hyperbole of the highest order.
- ecnahc515 6y agoNot really. They require a basic understanding of higher order functions and often heavily use closures. Those moderately advanced concepts. It’s also sometimes harder to write efficiently to avoid multiple iterations over the same collection. I think many many people are way more comfortable with loops than people are with map/filter.
- solidasparagus 6y agoTS and Golang aren't comparable. I use both and I've never had a case where I needed to decide between the two. Golang is a high performance, modern language without the low-level or legacy headaches of comparably performant languages. Golang was written for an era where network communication and concurrency are commonly necessities and those use cases feel very natural. Typescript is JS (a conversation ending advantage in many cases) and so the concurrency model is amazing in some cases (e.g. when most of the work is async stuff like API calls) and pretty terrible in others (parallelizable computational work). Golang was designed for getting shit done. If you are a big believer in OOP, then Golang feels underfeatured. But if you don't really care about OOP and you just want some of the advantages like basic inheritance, type safety, etc, Golang has everything you need to write performant, effective code quickly (there are use cases where that isn't true I'm sure, but, for me, Go's type system has been helpful and not a hinderance). There's nothing wrong with using the empty interface when you need to (any more than using any in TS, which you have to do in many applications). I've found that Golang codebases are easy to pick up. I think everyone has some part of the Go style that they think is ugly (I 100% find append ugly), but for me this has mostly been inconsequential stuff - it has never gotten in the way of me solving business problems with high performance code. The tooling is the same (at least if you are using modules). It does its job well enough and then gets out of the way while you create business value. I don't know your use case so this might not be relevant, but sometimes people will overuse for loops and slices when they might find it easier in Golang to pass around channels and use the pipeline pattern[1]. For me, Golang is like Python but with static typing and high performance. Fast to implement, easy to read, and focused on getting code out the door. [1] https://blog.golang.org/pipelines https://blog.golang.org/pipelines
- tigershark 6y agoMaybe you are not really taking full advantage of the powerful type system in typescript if you don’t see any lacks in go type system and if you think that using ‘any’ or the empty interface is perfectly normal?
- AlphaSite 6y agoIMO Go's biggest issue is its lack of the functional features which have trickled into most languages (although arguably without generics, this is impossible to implement). I dont particularly want Haskell with semi colons and braces, but a functional style definitely has its place. Just like Go has a subset of the traditional object oriented style, i think there is a place for a subset of functional.
- harikb 6y agoI would be embarrassed to admit the amount of times I have discovered this in my Python code for foo in ... if i in foo: creating something of quadratic complexity! Yes, I would rather take the explicitly verbose Go code To be clear: If foo is a dict, we have one loop. If foo is a list, we have two loops. If accidentally happens to be a string, even then it is nested loops
- setr 6y agoIsn't this just an issue of having types, versus not? Although I do remember trying racket, where they solved the same problem by naming functions dict-remove set-remove hash-remove vector-drop etc, which does the job but never have I been more offended thinking I was going in for its abstraction capabilities
- kixiQu 6y agoThis seems like a misunderstanding of quadratic complexity. If every i in every foo is checked/operated upon once, that's still linear, no matter if the nesting structure requires nesting flow control.
- sickcodebruh 6y agoI share a lot of these opinions. The language and especially its type system feel like toys when comparing it to TS. I still really enjoy working with it for the right projects, which tend to be very straightforward little servers that need to do one or a couple things very well. For me, when the task is right, “limiting” becomes “straightforward and uncomplicated” and the things it does well really shine. The language and its type system encourage a simplicity of thought that I find refreshing when compared to the power and complexity of modern languages. I also can’t say enough for the joy of deploying Go binaries over TypeScript projects. Even so, I’m waiting for generics before I use it for anything really significant. As is right now, I could see myself becoming frustrated with the Zen of Go if I had to use it every day. Just give me map, damn it!
- tmerr 6y agoComplicated languages come with an explosion in number of ways to do things. Rust is great but I waste a lot of cycles thinking about how to structure the code instead of the actual problem. What is cleaner here using a loop or a higher order function? Should I use if let to make the code a little shorter? Should I use that question mark trick to propagate the error? Do I use the expression or statement form of ifs? Do all of the features in your language really make you more productive, or are the gains offset by the cognitive burden of dealing with them? And what is the cost of having many ways to do things in the context of a code review? What about when reading other people's code? What about when writing automatic tooling?
- eweise 6y agoI get the feeling that Go programmers came from some other imperative language and got burned by some OO features. I feel kind of bad for them. I hope they never discover modern functional features or they will realize how much of their life was wasted writing pointless boilerplate.
- pm90 6y agoAnd I feel bad for those who pontificate over the lack of features for a language that’s easy to use, has a simple build system and allows for solving many classes of problems very easily. Golang is popular for a reason. It is popular even among programmers that enjoy using other languages. No need to feel bad for programmers who are happily building things.
- icholy 6y agoThe time spent writing boilerplate is completely negligible to the amount of time spent finding the "perfect" combination of language features to express your problem. I write production ready code in Go way faster than in any other language I've used.
- loopz 6y agoWhat you feel about what you don't understand, isn't really important to anyone else though. Go provides less is more as a feature, but would be invisible unless the dev cared about seeking simplicity and performance.
- kovac 6y agoGo is not simple (conceptually) by any strecth of imagination. Golang has pointers bolted on as if they are a real thing. Like, what's the point of exposing pointers without the pointer arithmetic when modern languages have come up with simpler ways to think about accessing memory? So, as a Go developer are you supposed to understand pointers or not? Similarly with Go routines, people boast about them as if they are a silver bullet for concurrent programming. But then, you also have and need to use sync primitives like mutexes sometimes. So, you still need to understand accessing shared mutable state and it's challenges well to use Go which is the actually complex part of concurrent programming. So, I don't know what people mean when they say Golang is simpler. I find it an ugly, weird and a hyped up language. The languages I consider simple are C and Python. C is simple because it's a small language and Python because it truly abstracts away the low level details. Golang is an opinionated (an quite an unimpressive) language with pros and cons like any other language. Currently, with more cons than pros, IMHO.
- zemo 6y agoa quick grep on my project and I'm counting 779 functions. the empty interface appears in 12 of the 779 function signatures. If you find yourself constantly using the empty interface it's because you don't know the language, not because it's necessary.
- loopz 6y agoGo is designed to be performant by default, so expensive operations will stick out in code. It is high level, but also like a "better C".
- apta 6y agoOnce Java gets green threads (project Loom), it will be a no-brainer to pick it when the choice comes between it and golang. Even now, it's almost a no-brainer with superior features and GCs, including the new low latency ZGC.