Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
New case studies about Google’s use of Go (googleblog.com)
218 points by 0xedb on Aug 27, 2020 | hide | past | favorite | 264 comments


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.


TS 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


> Golang is like Python [...] Fast to implement, easy to read

I disagree. Python is often described as "executable pseudocode" - for example, to delete the `i`th element from a list `a` you use `del a[i]`.

In Go, it's much more convoluted: `a = append(a[:i], a[i+1:]...)`. Plus, without generics, you can't even easily hide that inside a function! There's a whole page of these "tricks" that are necessary to perform basic operations on slices: https://github.com/golang/go/wiki/SliceTricks


Interesting. I didn’t know you could do that in python with a list.

It would be trivial for Go to support the delete keyword on slices (mapping to the statement you noted), but I think it would be a bad idea. Sometimes you want an operation to be awkward intentionally because it’s fundamentally costly. Hiding that cost by making everything look the same doesn’t always help the programmer. Languages should be powerful, but there should be an intuitive relationship between the code the computational complexity (not exact, but intuitive).

I’m sure there are counter examples, but I think Go generally does a good job at this. Plain loops are standard, make, append, new, delete, etc. have obvious costs. Error handling is explicit.


> `a = append(a[:i], a[i+1:]...)`

Not only is this ugly and unintuitive (“what function do I call to delete an element?”; “append”), according to the linked page it can also cause a memory leak?!


On the other hand, it's very clear about what's actually happening when you delete an element of an array.

I'm not a C guy, but I figure doing this in C would involve several lines of mmemove, with loads of error checking[1]. So the Go version is about as ergonomic as you can get without obscuring what's going on.

[1] - I guess you'd do something like: memmove(a+i+1, a+i, sizeof(element) * (a->len - i)) with a whole load of checks to make sure everything's in order. I think C has the advantage of being utterly explicit about what is actually happening, but I think a higher level thing like append() is kind of nice when you don't want to think hard about, say, inserting an element in the middle of an array.


Yeah, Python is much much more readable than Go. I feel like performance focused languages are always less readable because the language needs to give you more control and I think Golang lets you work at a pretty high level of abstraction while still having plenty of control on performance. Once you know Go, it's pretty easy to read someone else's code, which I think is really nice. But "easy to read" might have been a little bit of a stretch.


IMO 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.


What do you miss? All I've ever really needed is the ability to pass around functions as first class primitives which Golang has.


I always cringe when people proclaim that they need to "get shit done". It often pays to be mindful of what is getting done as a result.


I think some people feel productive when they write out a big loop, but to me it’s wasted effort. I want to write

  col.filter(_.isReady).map(convertToX).any(_.color == BLUE)
and generate whatever fused loops make that work. I don’t want to write and review loop boilerplate by hand for the same reason that I don’t want to customize the stack frame layout when I call a function.


I've never found it much more painful to write:

  for i, c in range col {
    if c.isReady && convertToX(c).color == "BLUE":
      return True
  }
(which is not to say I don't miss the map/filter syntax - although I don't miss the bugs related to lazy execution in stuff like LINQ or Spark)


That’s actually pretty good. Most people would use three more lines to create a temporary and break after setting it, and three to nine more depending on how many steps require idiomatic Go error handling.


Would most people actually do that? That example seems like pretty idiomatic Go. I imagine junior developers would write that.


I would typically expect

  anyBlue := false
  for _, c in range col {
          ready, err := c.IsReady()
          if err != nil {
                  return nil, fmt.Errorf("isReady failed: %v", err)
          }
          if !ready {
                  continue
          }
          x, err := ConvertToX(c)
          if err != nil {
                  return nil, fmt.Errorf("convertToX failed: %v", err)
          }
          color, err := x.GetColor()
          if err != nil {
                  return nil, fmt.Errorf("getColor failed: %v", err)
          }
          if color == BLUE {
                  anyBlue = true
                  break
          }
  }
which badly obscures what’s going on but demands no cleverness at all (except that some might forget the “break” and still get the right answer).


If IsReady, ConvertToX, and GetColor can return errors then this isn't that far off. But then you're not making an apples to apples comparison. You would have to extend your functional example so that it also handles errors. Unless it already does, and I am missing something.


What I wrote should be pretty close to valid Scala, which handles exceptions. I can imagine wanting to skip an isReady failure, which looks like

  col.filter(c => Try(c.isReady).getOrElse(false))
  .map(convertToX).any(_.color == BLUE)


I see. Then in part the comparison is showing off exception handling, not FP.

Rust is a good example of functional lang without exceptions (panics aside).

In Rust there are many cases where I could use FP but opt not to because it can make error handling more awkward. For example to collect the result of a map operation to a vector, and if there is an error along the way you want to abort the entire operation. In functional this means collecting to a Result<Vec<T>>. Not sure if I'm just tired today but I can think of how to do it in 5 seconds with a loop. I suspect functional solution would be uglier.


Rust’s collect will do this for you. It’s even an example in the documentation.


Thanks! I learned something new.:)

https://doc.rust-lang.org/stable/rust-by-example/error/iter_...

This is easy to miss if you are mainly reading reference docs. I probably read the getting started guide at a time before there was a section on it.

My other comment in this thread comes to mind https://news.ycombinator.com/item?id=24300057


I was thinking of the final example in https://doc.rust-lang.org/stable/std/iter/trait.Iterator.htm... , glad we have it in both places!

I don’t personally really agree with what you’ve said, but that’s fine. Different people perceive things differently.


No problems. There are enough dimensions involved in what makes a language good that Im pretty sure I could rationalize why any language is better than another, measured along only one of them.

Robustness. Speed. Simplicity. Easiness. Conciseness. Writability. Readability.

Hard to tell which are independent vs correlated, let alone how they factor into productivity. And productivity is also a function of the kind of problem you work on.


It really doesn't matter day to day once you're in the loop (cough). I agree, it's an ugly language on the face of it, but you get over that quickly. You come to appreciate the language as a whole.

A bigger concern when I started out with Go was the imports/lack of versioning, and at the time the lack of official package manager.


This style makes developer forget the underlying costs though. It feels productive but it is harder to understand what work computer will do. Go is designed to be imperative, so is a complementary language.


That's true and we should embrace it. Higher-level languages should empower us. We should use profilers to measure actual bottlenecks when necessary, not make every potential bottleneck more painful to write and read forever.


You can get a ton done in Typescript or Python or Ruby. And in addition to type systems being developed to assure type safety in the most dynamic of languages, you also can write tests and draw on the community knowledge of countless programmers who know your language. Obviously if performance & certain performance first libraries are first priority for you, choose a very computationally efficient lang. But it’s a toothless argument in 2020 to say when following best practices you are inevitably going to write flawed, incorrect code because you’re starting in a dynamic language.


I'm also majorly turned off by this attitude. We're knowledge workers - ostensibly paid nice salaries to think deeply and find reasonable solutions to hard problems, not just to turn a crank and shit out code as fast as possible. Sure, this is not your job 24/7, and there will always be boring code to write, but still, have some pride in your craft, you know?


The point of code is readability and runtime, not ego-stroking. Fast compile times are a bonus!


Are you suggesting that Golang leads to to poor quality software? That hasn't been my experience.


No, I specifically quote words from the comment to which I'm replying.

The problem is language-independent, but is more pronounced among adepts of "practical" languages and tools.


Maybe 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?


>Golang was designed for getting shit done

That's indeed a good way to explain the utility driven nature of Go. I've been predominantly using OOP languages before and Go's deliberate lack of OOP features was although uncomfortable at first, the advantages of getting things done fast far outweighed it later when I released production applications with it.

>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.

I was tired of adding disclaimer when teaching Python, that when you want to extract performance out of it you should also learn 'C/C++'. Go serves as a perfect replacement to Python where performance is a necessity, I don't see where that would be false in a production environment where 'code performance == capital efficiency'.


I 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#.


I 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.


> 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


I 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.


Python 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.


I 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!


> 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.)


That'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.


Super agree. Speedy compilation time of Go was my favorite feature. TS compilation is frustratingly heavy.


TypeScript has way more advanced type system so there is a price you pay for that.


IIUC, this is specifically a problem with the TS build system/runtime, not because it’s typed. Deno is attempting to solve that.


the 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=2y0pmRJNkLA


map/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.


And 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).


Come on, map and filter difficult? That's hyperbole of the highest order.


Not 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.


I'd settle for comprehensions. It already has generic for/range so why not. That would cover a lot of boilerplate annoyances.


Correctness isn't about fun, although fun is definitely a side effect. I agree Go is easier to read if you're primarily familiar with C style imperative programming, but once you've strayed from that a bit, a PR in Typescript is no more difficult to review than one in Go. The big benefit of languages with more expressive type systems is the confidence you get that your code will work as expected if it compiles - I felt this in Swift more than in TS, and very little in Go.


I love go but the OP is completely right. Lack of basic collection functions is incredibly aggravating and slows down productivity substantially. At least it's not as bad as Java.


I'm not sure how you can have that opinion of Java when Go is basically Java pre-generics. Especially in the context of collection functions. Java's stream API is simply amazing.


Yeah sorry, the Java collections API is pretty great. I meant in terms of raw boilerplate the language requires you to type to get anything done. This is definitely improving, and you can use things like Project Lombok to generate a lot of it.


Java's photocopy of .NET's Linq in the form of "Streams" is usable.


> the key is simplicity

Simplicity (in language features) can lead to complexity (in code) that is hard to maintain.


I 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!


I 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


This 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.


Isn'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


Complicated 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?


I 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.


And 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.


What 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.


Go 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.


Go spec is quite short and understandable. The implementation handle quite alot for you, which is not simple, but makes many applications easy to write. Code is fast to write and easy to read. Golang really has 2 types of references, not pointers. I find C and Python slow and tedious to use, and would rather not share memory if I can avoid it, including using pointers (use map instead). It depends what one wants from a language, where golang fills a nice untraditional niche where experience and newcomers can meet. I find Go optimizes more concerns than any other language, which in turn makes it an opinionated balance of several dimensions.


The 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.


You'll be happy with the latest developments: https://blog.golang.org/generics-next-step


No need to convince. If you've got something working nicely why would e.g. I spend my energy to convince you otherwise.


Go 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".


a 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.


This 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.


Other 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?


I'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.


Many 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.


I don't know about that. I find relentless cynicism/negativity to be much more difficult to ignore than positive comments. I tend to think this is how we are wired as humans.


I find both positivity and negativity annoying, bleh! ;)

Joke aside, how about we all complain about your favourite language in every post? It over time becomes irrelevant to those who grok the language.


It'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.


Once 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.


The 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 ) for example composes interface types.


This 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.


Interface composition is product of types, not sum.


I absolutely love using Go. The logical flows for my programs are always so clean and easy to follow thanks to the language. Contrast to C++ in which spaghetti and magic is basically idiomatic. The only downside I can think of is that error/crash recovery is pretty tricky, but it's only really a concern if you're careless with your goroutines.

Whenever I work in Go, I have a lot more confidence in the efficiency of resource usage, and sense of stability that I just don't get from something like Node.js, where I'm constantly wondering... are any of these 1000s of dependencies going to suddenly do something weird like hijack my .env file? How is my program managing memory and overhead when it needs to interface with the kernel via a C++ wrapper? Are these machine resources even being capitalized on by Node.js properly? etc.

I've heard a lot of great things about Rust, and I've touched on it a bit, but Go is just awesome for its abstractions, ease-of-use, and of course insanely fast compile times.


I have a love/hate relationship with Rust. I love the type system as enthusiast, but as project lead I can't justify relying on so many (partly immature) third party dependencies for business critical stuff.


I had similar feelings when I was hired to write in Go about 3 years ago. Coming from Java where everything (including the kitchen sink) was available for import, it took some time to re-adjust my mindset of having to seek out libraries and thoroughly vet them.

After a while, I kinda started to dig having to do it. You end up having a more personal connection with the dependencies you pick which makes it easier to contribute back upstream.

The one downside of being around in this stage of a language's ecosystem development is you can potentially get some pretty undesirable fragmentation.

A good example that comes to mind is one of the original Go library to interact with Zookeeper. There's like 6 maintained forks of that library due to the original author bowing out of maintaining it.


This is exactly what I've been thinking.

Right now you need enthusiasts and a project that can either accept or handle the risks brought on by the immature ecosystem.

Later on, Rust will most definitely be a huge thing. It's just not the right choice for everything - even if the community has a habit of pumping out "X - but with Rust" projects.


"Spaghetti" means that the code is tangled because of improper control flow usage, lack of adequate control flow syntax or the language encouraging certain patterns. There are very few mainstream programming languages which can be said to encourage writing spaghetti code, I can think of VB6 and early versions of PHP which encouraged mixing e.g. HTML with code. Claiming that C++ spaghetti code is idiomatic is nonsense. There are many very popular references on how to structure and design C++ code and idiomatic C++ code is making use of structural, OOP or functional programming where appropriate.

"Magic" refers to the implementation of certain language or library features directly in the compiler without using the language features. C++ is on the least magical side, since the entire standard library and major libraries are implemented exclusively using language features. Everything is specified and C++ is one of the very few languages which has an international standard. It's especially odd to call other languages out for this when Go for example has magical generic data structures when this feature isn't supported by the language.

Next time consider limiting your comment to praising Go and don't pretend that you know enough about other languages to draw a meaningful comparison.


While I do trust Rob Pike to not let personal biases sway his writing, I do have to wonder if the case studies weren't selecting because they were positive. So I'm curious: does anyone have a case study where using Go was a disaster?

Every language has things it's good at, and things it's bad at. Where does Go not do well?


Let me just say that I've been at Google for almost 9 years, and have recently started looking for work elsewhere and it seems that Go is far more popular outside of Google than inside it. Which disappoints me because my experiences with the language internally have biased me such that I have no desire to go use it elsewhere.

I've said this before, but I think it's a bit dishonest to sell this as a "Google language." It is an accepted language here, along with Python, Java, JS/TS, Dart, and C++. But it is by no means dominant.

To put it another way, it seems if the goal is to avoid working in Go I am better off staying @ Google than leaving. And that's weird, and maybe revealing.


If you look at the way the rest of the industry cargo-cults Google, Go almost looks like a false flag attack to increase Google's competitive advantage while the cargo-cults drown in boilerplate and an inability to abstract.


My current and last positions both involve(d) writing (mostly) Go code, so it's definitely possible to find Go jobs within Google.


OP wants to avoid using golang, not to find a job where he can use it.


This comment doesn’t tell me anything about why you don’t like go, just that you don’t like it.


Other people have touched on that and I've opined on it in the past, I don't think this is the thread for that. I think you'll find HN is a divided community on golang. Myself I find the language... kind of insulting... in its lack of basic modern constructs. I find its emerging prevalence to be a concerning trend, and I think it's going to lead to a lot of brittle, boilerplate code. Obviously others disagree. I'll leave it at that.


But whats the point of coming in this thread and insulting the language repeatedly without explaining any of your insults? why do you feel like this type of unconstructive criticism is appropriate in this thread, and actually explaining your point of view is not?


The thread is about Go language adoption, and so I stayed on that topic. I made a remark about my observations of the language adoption within Google, and what I perceive outside of Google. The bits about my tastes for this are a personal commentary and are related to why I'm interested in this topic: I don't like the language and don't want to work in it.

I don't really care that you find that un-constructive, as you can go elsewhere to get people's critiques of the language, there are plenty of them and they come up every time someone posts about Go here. My opinion is certainly not unique on this subject.


I just find it frustrating that your comment is "i'm a google engineer and I hate the language and so does everyone else at google" but you refuse to explain why you feel that way. As someone who likes go, I find this comment to be basically "go is bad because google engineers dont like it" which is the exact type of appeal to authority/cargo culting you seem to be criticizing.

If you're going to trash something at least put in enough effort to explain yourself. Otherwise I think this thread was better off without your comment.


Pretty sure it wasn't "so does everyone else at Google." I challenge you to find that quote. Not at all representative of what I said. Stop casting aspersions on me.

I think you might be a little too emotionally attached to Go? I am allowed to have a subjective opinion on Go and voice it in public discussion forum. This is not a scientific paper or journal article.


You're allowed to do whatever you want, as am I. I claim that your comment was unconstructive and paraphrased the meaning of your comment. I didn't learn anything about the weaknesses of Go from reading your comment, I learned that you don't like it and there was a vague suggestion that it is unpopular at google, and that the reason its popular outside of google has to do with cargo culting. But you neglected to express why you thought its weaknesses of go (what are those weaknesses?) that leads to this situation.

I would genuinely like to know what your criticism of the language is, but you haven't offered any. The comment you wrote does not add any clarity to the discussion of Go, in fact I think it takes away clarity by relying on suggestion and avoiding grappling with any details. I think it was not a useful contribution to this thread. I'll leave it at that.


cmrdporcupine stated, at least once, that he didn't consider his reasons for disliking Go to be on-topic for this thread. You seem obsessed with trying to pry the reason out of him. He said he's not going to answer; let it go.

If you have to have an answer, he said he's opined on it in the past. Go trawl through his past comments. (Google search might help.)


> it seems that Go is far more popular outside of Google than inside it

Blame the cargo cult and hype driven development for that one.


I know a case (second hand) where they migrated from a Java backend to Go, then had to roll it all back to Java because it was too hard and error prone to maintain. This is a very successful business, not a startup. No idea why they felt they had to migrate to Go in the first place.

I'd rather not mention the company, even though I did not work there.


And as a counterpoint there are many non-hearsay examples where teams migrated large projects from C++/Java/Python/Ruby/JavaScript to Go.

Described publicly like Dropbox's backend migration to Go: https://twitter.com/jamwt/status/629727590782099456

I could give you tens examples of that, many have been posted on HN.


No need to counterpoint my example. The original list of case studies already lists Go's success stories.

I was just providing the example the parent post was asking about. And note it's "hearsay" to you only because I didn't name the company and people involved -- because I was told this in confidence -- but this is a major company where I'm from, and their attempt at adopting Go ended up in disaster. Just a data point, that's all.


Yeesh, I can't imagine migrating a large backend codebase from any language to any language.

And we're talking about migrating from Java..which is extremely well supported and probably the easiest language to hire for..


Concurrency is something that Go makes much easier, or at least more ergonomic, that Java with Runnables and ExecutorPools.


It makes it easier to start concurrent stuff, but without ready-to-use type-safe abstractions like Java provides I'd say it's far harder to make correct concurrent stuff in Go. And while the race detector is wonderful, especially since it's baked in, it's nowhere near sufficient.


I disagree. There is so much boilerplate involved with managing concurrency in golang compared to Java. It's very error prone in practice and difficult to extend and manage. golang has nothing remotely close to `java.util.concurrent`.


Go is officially banned by Google for Fuchsia: https://fuchsia.dev/fuchsia-src/contribute/governance/policy...


"Banned", while technically accurate, gives the wrong connotation. More precisely, it wasn't selected as one of the languages for the project. That is, Fuchsia has a set of technical challenges, and it is a reasonable engineering practice to select a minimal set of languages to tackle those challenges. Go's doesn't have a unique niche or a dominate strength in an important area when it comes to Fuchsia, so they're not using it. (As I understand that having read your link previously.)


There was discussion about this 6 months ago, such as this comment.

https://news.ycombinator.com/item?id=22412475



This is a puzzling decision on Discord's part, because they found the single line of code causing their problem and they didn't think to change that line of code for their own needs. Go distributions include the source for Go itself, so building your own Go binary with your own changes incorporated is dead easy. And, the change they needed is a single-line change, which means it's easy to bring that change forward as new versions of Go are released.

Discord: haha, no, that's silly! let's spend 100,000x more effort and rewrite it all in another language!

Now, before those of you who learned to argue on the internet extrapolate what I wrote and imagine that I wrote words I didn't write: I'm not saying that Go should never be abandoned for another language. I'm saying that this particular example of this particular choice puzzles me, because of the reasons stated, and ONLY the reasons stated.


Besides all you said, Discord client is electron based bloated software. So it just seems a case when some engineers itching to write Rust and decided to make virtue out of it.


But they’re specifically talking about a server component here. Using Electron on the client doesn’t magically make their need for a high performance backend disappear. They’re still having to make all those clients work and deliver voice chat to millions of simultaneous users.


Yes of course they are. Further I understand the "strategic decisions", "markets have spoken" , "faster feature due to single codebase" justifications to Electron usage. To me it just feels like saying we care about our servers meanwhile users can eat crap.


Yeah, one is free, one isnt


Bad UX is not free at all.


There's a Serbo-Croatian proverb: "what you don't have in head you have in feet." That is, what you can't do by thinking a little bit means you must do by expending pointless effort instead.


Not to mention they could’ve probably just updated their old go runtime...


IIRC none of the available Go releases at the time the decision to switch to Rust was made (<=1.10, I think?) addressed their particular issue, and by the time a Go release did fix their issue (1.12?) they were pretty far along with their rewrite.

Not entirely sure that I have the Go versions right, but that's what I remembered off the top of my head.


Just found a comment by a Discord engineer that says that they did try upgrading their Go runtime (presumably when the decision to rewrite was made) [0]:

> Another Discord engineer chiming in here. I worked on trying to fix these spikes on the Go service for a couple weeks. We did indeed try moving up the latest Go at the time (1.10) but this had no effect.

[0]: https://old.reddit.com/r/programming/comments/eyuebc/why_dis...


That's not what the article is saying.

It describes a rewrite of a single service from Go to Rust.

Reading between the lines, a rather simple piece of code.

At no point it implies that Discord rewrote all their Go code in Rust and completely abandoned Go.


Top-voted comment on that post raises some red flags.

> Any reason you’re using 3-year-old Go 1.9.2 but you’re okay using Rust nightly?


A Reddit comment by a Discord engineer addresses the old Go part [0]:

> Another Discord engineer chiming in here. I worked on trying to fix these spikes on the Go service for a couple weeks. We did indeed try moving up the latest Go at the time (1.10) but this had no effect.

[0]: https://old.reddit.com/r/programming/comments/eyuebc/why_dis...


Case studies like these are always selected because they’re positive; you don’t have to wonder about the biases. Someone else might want to collect the negative cases; Discord, for instance, and their fights with the GC.


I had looked at the Discord GC blog issue [1] fairly carefully, and it certainly seemed that specific GC latency issue they hit and blogged about would have been solved by upgrading to a modern Go version....

Also, after publishing that blog, they also said they had wanted to try Rust for other reasons:

wanted to try out rust as well for services like this, due to adoption elsewhere in the company. Also, after upgrading between 4 golang versions on this service and noticing it didn't materially change performance, we decided to just spend our time on the rewrite (for fun, and latency) and to get a head start into the asynchronous rust ecosystem. [2]

And nothing wrong with that decision from my point of view (Rust is great!), but I believe they could have solved it without dropping Go for that particular service that they blogged about, at least as far as I was able to understand.

[1] https://blog.discord.com/why-discord-is-switching-from-go-to...

[2] https://news.ycombinator.com/item?id=22239707


> it certainly seemed that specific GC latency issue they hit and blogged about would have been solved by upgrading to a modern Go version....

Do you know if that was the case when the decision to switch was made? They said elsewhere they tried Go 1.7-1.10 and none of those solved their issue, and at least back when the blog post was released I couldn't figure out whether the fix for the corresponding issue was known to have been slated for release in the next Go release.


> Do you know if that was the case when the decision to switch was made?

It’s a good question.

The timing is a bit confusing because the blog was apparently published a bit after the fact, but I think I saw that they said they made the decision mid 2019.

Go 1.12 seemed to address their latency issue, which was available as GA in Feb 2019.

That’s based on some retroactive benchmarks on a set of old Go versions starting with 1.9 and targeting what they described as the problem and symptoms.

Things seemed to line up, but I can’t be sure.

I don’t know if Go 1.11 would have addressed their issue.

(In general, Go GC tail latencies including for large heaps have improved a bunch since the last version they said they tried, which I think was Go 1.10).

In any event, they saw a problem, and made a rationale decision for multiple rationale reasons.


After digging a bit more, I found a comment from a Discord engineer that seems to clear things up [0]:

> Another Discord engineer chiming in here. I worked on trying to fix these spikes on the Go service for a couple weeks. We did indeed try moving up the latest Go at the time (1.10) but this had no effect.

So I guess that means that there's a reasonable chance that they didn't see a fix on the horizon.

That being said, I have no idea if work to fix this issue was visible on Go's Github, so maybe the Discord engineers were unaware of said work or were unhappy with the pace of progress.

Kind of miffed at myself for missing that comment, since it directly addresses my question, but at least it's answered now.

[0]: https://old.reddit.com/r/programming/comments/eyuebc/why_dis...


Based on reading through various posts from Discord people after that blog was posted, my understanding was there was a material gap in time between the last time they tried in earnest to solve the latency issue with Go (with Go 1.10, as in your quote) vs. when they later did the re-write in Rust.

It seems during that gap in time, the Go runtime team happened to solve their problem, which was GA in Go 1.12 in Feb 2019, which was prior to them doing the re-write in Rust, at least as far as I was able to follow.

One imprecise quote on timing of the re-write: [1]

This blog post perhaps is a bit "after the fact" we had made the switch over mid 2019

It's not crazy for someone to put aside a problem for a while, and then upon returning to the problem some time later decide to go a different route without re-exploring prior solutions, if that is what happened.

All that said, I might have misunderstood the timing, and I'm trying to avoid going back over all the various forums they commented in to find a better quote on timing ;-)

[1] https://news.ycombinator.com/item?id=22239707


I think it comes down to what "we had made the switch over mid 2019" is supposed to mean. I had interpreted that as being the time the Rust implementation was put into production and the Go implementation retired, with the rewrite starting some time before then, but I don't really have any strong evidence to support that interpretation (and that interpretation doesn't say anything about the actual point at which the rewrite decision was made).

The situation you describe is certainly plausible, though. Shame that the chances of finding out what actually happened are quite low at this point.


I don't think anyone read that case study as somehow disqualifying for Go, so there's no need to litigate it; it's an example of a "Go -> Something Else" case study, that's all.


True, and it was an interesting case study.


I did run into one Go codebase that was closures all the way down. Due to limited abstractions, closures were created and passed around and returned everywhere through so many layers with arbitrary generic naming. It was the worst. At one point I wondered if it was a ploy to ensure employment but I don't think it was.


I built (at Google) a prototype system in Go, then rewrote complete in C++:

- Go was too slow and GC too much overhead (real time analytics)

- Error handling and propagation is insanely verbose in Go, the C++ actually was more concise

- lack of generics made it impossible to reuse complex high-performance data structures and algorithms even within the project

Haven't looked back and between C++, Rust, Swift and Python, I'd never choose to use Go again.


We tried to build a JS runtime in Go and it was a disaster. .NET was actually a better choice, though we ultimately went with Rust (and ultimately, ultimately went with Deno ... which also started as Go).


Anything that has to do with UI in my opinion. Go's lack of classes (factories, inheritance, etc) and verbosity make graphical layouts very, very tedious.


I think this is only true for OOP-style "widget-based" UI toolkits. I've had a very good time writing console UIs using a reactive style; obviously console UIs are simpler, but I think when people want inheritance in UIs, it's for things like 2D layout (in typical OOP toolkits, every widget type is derived from some base Widget class that does layout things) which are also present in console UIs.

I would be interested to hear rebuttals or other thoughts.


Can I ask which reactive-style console UI library you have been enjoying using? Or was it a custom thing you made from scratch?


Custom, made from scratch probably 5 years ago just for fun.


Honestly any low level/system code is pretty disastrous in Go.

Edit:

Just to add to that statement: the work stealing goroutine runtime is particularly problematic, certain things are even impossible in go due to it. If you look at runc, large parts of it are written in C and called during init before the runtime is started.


Even higher level programs are quite terrible in golang. It seems it's only good for small (usually networked) tools that can perhaps make use of concurrency.


In practice, golang is quite verbose (yes, more than Java) and its error handling is error prone. It has weak abstractions, and lack of proper enums also lend to more verbose and error prone code. Monitoring is poor compared to the JVM/.NET, and performance is worse in general. It has very questionable, if not outright bad design decisions (e.g. they wanted to save on keywords so they don't have public/private, so changing the visibility of a variable or function now results in a huge diff if it's used in many places). The list is too long to elaborate on in a few paragraphs.


> so changing the visibility of a variable or function now results in a huge diff if it's used in many places)

You can create an exported version of the function (calling into the unexported one), no diff except the new function.

But also just updating all the callsights is usually not a huge issue, especially if you are using an IDE such as GoLand.


> You can create an exported version of the function

These are the kinds of hacks that show that golang wasn't really designed for "programming in the large", despite their claims.

I've used goland, and the actual renaming is generally fine (it means it works correctly when needed). However, that doesn't mean that there isn't a lot of friction


I don't agree with the term "hack" here. Different is not "hack".

I maintain some very large codebases. This has never been an issue.

If one decides to export a function, the only callers of that function will be from within the package it was defined in already. Even within a package, how many call sites will there actually be and do they need to use the exported version of the function?

I'm not saying it's good, or bad, just that in my (fairly extensive) experience it has not been a problem. I do recognize that some people may have problems with it, though.


My experience has been otherwise, it's been extremely friction-inducing and I had to go out of my way to split up diffs into smaller ones in order to make it clear what was going on. A language like Java or C# would have just had a single line difference (`-private +public`) and be done.


You can see more very exciting case studies of companies using Go here, didn't know until now Twitch or Facebook (and even Target!) uses Go a lot.

https://go.dev/solutions/#case-studies


The main objective of the blog post was to signal that 3 more cases were added to the page you mentioned. So everyone that has read the submitted post has probably already seen the link in "we’ve posted sixteen case studies from end users around the world talking about how they use Go".


All backend systems at save a few minor exceptions are written in Go :)


This isn't true at all. Google still runs a lot of backend on Java, for example.


And their backends in C++ dwarf Java and Go backends combined.


In 2015 they were saying that the core of web search (and the large majority of Borg cores) was C++ but the rest of google3 was a 50:50 mix of C++ and Java with a smattering of Python. Nobody I knew was looking seriously at Go.


I think weighting it by lines of code is pretty misleading. You have to write a zillion lines to make "hello, world!" work in your new language inside their full-custom production environment. I prefer to think of language share in terms of resources committed.


This comment was about Twitch :'( I guess you guys thought I was talking about something else


Anecdote of one here, but I think Go's best use case is building monoliths (queue the irony of it being used for a lot of microservice work). The way the language works and the readability it provides really removes a lot of the arguments for breaking apart a monolith, and the performance guarantees it has around parallelism and goroutines make combining your async task processing into your main binary trivial. I'd go so far as to say I don't think anything beats a Go monolith in terms of developer velocity, code quality, and performance.


That's an interesting take. Do you have personal experience that you could share more detail on? Or even more public projects


I would say the most prolific one is Kubernetes. Sure it has some parts broken out (controller manager, scheduler), but the main API server is a pretty big Go monolith.

At a far smaller scale, the SaaS product my company built, Domestica (https://about.domestica.app), is a Go monolith. It has an integrated job/cron queue using PostgreSQL included as well, all within the same binary. This makes it easy for us to distribute it as a Docker image to our users who want a private instance (https://hub.docker.com/r/candiddev/domestica).


Go is super productive. My day-to-day responsibilities include development in .NET and Go. A full day working in Go is like a having a pleasant day off. On the other hand, .NET is so cumbersome, complex and verbose (I've been using it since its inception), that I'd rather abandon it for good if possible.


.NET is not a language. Are you using C#, VB.NET or F#?


You're absolutely right. In majority of cases, when people say .NET, they mean .NET & C#. VB.NET or F# are pretty much always explicitly mentioned as they're not the default choice for .NET development.


What kind of development do you do if you don't mind me asking?


Of course not. Nowadays it's pretty much about implementing HTTP REST APIs and consuming APIs (HTTP, SOAP, gRPC). We have both monoliths and micro services in production.


Efficient user-space threads (go routines) and the way go lends itself to the reactor pattern is exactly why is has been the language of choice for the company I work for. We use it to power all of our distributed microservices which process IoT packets from a stream. The performance and ease-of-use is heads and shoulders above everything else we tried before (mainly, Java with Kafka/Storm).


> Looking back from 2020, Go has succeeded in both ways: it is widely used both inside and outside Google, and its approaches to network concurrency and software engineering have had a noticeable effect on other languages and their tools.

Don’t know much about go myself, but I’m interested in examples of this.


Green threads without explicit language syntax for yielding - called goroutines influenced similar features in Kotlin. Unfortunately Kotlin is bound to working inside JVM and had to introduce “suspend” keyword.

This is a friendlier world to work in than explicit green threads using keywords like async/await in other languages (Dart, Rust, JS)


Clojure has goroutines on the JVM with core.async, no yield needed :)


You have to explicitly call out your async blocks though -- even worse!


Arguably opinionated formatters like prettier and black are a response to gofmt.


Benefits of this for large system projects cannot be understated. The notion that there's a many-to-one mapping between allowed representations of the source code and a canonical representation is very smart because it enables bidirectional preferences; not only can the main source make assumptions about code format independent of individual user preferences, but individual users can have preferences independent of the main source; code that is in a canonical format is easier to apply custom formatting to.

In addition, a canonical format makes it slightly easier to do plaintext search indexing, so you can get some of the benefits of having the code parsed into a full AST without needing to do that parsing.


Definitely but what about the impact of go's approach to network concurrency?


For one example, I believe Crystal is inspired by Go in this respect. https://crystal-lang.org/


asynchrony without async/await


Clojure has core.async heavily inspired from go.


I came to Go because some Kotlin CLI tools used too much memory and were clumsy to deploy.

I'm staying for the standard lib, tooling and stability.

Nothing gets out of the way better than Go.


Well, except for maybe a language that doesn't force you to remove (temporarily) unused imports and change your variable name to an underscore if you simply comment out the only section of code that used to refer to it, making your variable freshly un-used. I find there are some highly opinionated, unconfigurable aspects of the language that pretty much only waste time. They actually get in my way constantly.


I agree completely. It's so pragmatic. It's not sexy. It just does the damn job, and that's why I love it.


async/await colored functions is a disaster: https://journal.stuffwithstuff.com/2015/02/01/what-color-is-... And so many languages and ecosystems have fallen to this. Even C#, which is surprising since I expected them to know better. There was so much hype about async/await (nodejs was a big factor for this hype), that many languages adopted this without fully considering the long term maintenance nightmare it will create.

Because of this, I'm mostly interested in only Go and Java. Go obviously avoids the async/await trap with its core feature, goroutines. Java managed to resist this trap and has Project Loom coming which will give it the same feature as goroutines, but in a backwards compatible way.

Go is criticized for not having generics, but I appreciate the slower and more thoughtful way both languages add new features. Javascript, C#, etc. these languages seem to add whatever FOMO driven new hyped language feature is popular at the moment. Many complain about Go taking so long to add generics, just like many complained about lambdas in Java. But evolving a language should not be done quickly and recklessly.

My focus is still on Java, but I'm occasionally looking at Go to see what they're doing. It's interesting watching these two languages become more like each other (generics in Go and fibers in Java).


There's still some problem for async/await but I won't say it "disaster". I don't think Java is good by not improving async systems.

I like Go's thoughtful adoption but personally I wonder they can do faster.


Async/await solves a different problem than green threads. Async/await works well when you need to manage scheduling of a single thread (very common in UI or other cross runtime tasks). Implicit green threads are nice if all you care about is total throughput across all threads. Its not great for keeping a single thread responsive.


Async / await is just an abstraction over threads. It doesn't dictate how many threads are used.


I'm not sure what your point is exactly but I would disagree with the presented assertions none the less.

In C# async/await is essentially sugar around callbacks, which isn't really related to threads, per se. However, the language has the Task Parallel Library, and a Task promise type that has a lot of methods around scheduling and thread targeting. Essentially the TPL does dictate how many threads are used and is, as far as language design is concerned, inextricable from async/await.


My reply was in response to "Async/await works well when you need to manage scheduling of a single thread" My point being that it isn't limited to cases where you only have a single thread.


Ah, agreed. That's a case where it does well, not the only case.


> Go also powered Google’s development and launch of Kubernetes in 2014.

Wasn't k8s written originally in Java and only ported to Go later on?


I think it's fair to say both statements are true:

> Kubernetes was built on ideas that had been proven out at Google over the previous ten years with Borg. And Borg, itself, owed its existence to even earlier efforts at Google and beyond.

> Concretely, Kubernetes started as some prototypes from Brendan Burns combined with ongoing work from me and Craig McLuckie to better align the internal Google experience with the Google Cloud experience. Brendan, Craig, and I really wanted people to use this, so we made the case to build out this prototype as an open source project that would bring the best ideas from Borg out into the open.

> After we got the nod, it was time to actually build the system. We took Brendan’s prototype (in Java), rewrote it in Go, and built just enough to get the core ideas across. By this time the team had grown to include Ville Aikas, Tim Hockin, Brian Grant, Dawn Chen and Daniel Smith. Once we had something working, someone had to sign up to clean things up to get it ready for public launch. That ended up being me. Not knowing the significance at the time, I created a new repo, moved things over, and checked it in. So while I have the first public commit to the repo, there was work underway well before that.

https://kubernetes.io/blog/2018/06/06/4-years-of-k8s/


I tried very hard to bring go into my previous employers environment, but it was all for naught. They are too bought into the JavaScript stack. Case studies like this would have been super helpful in trying to make my claims.


I don't have the details of how you tried to push this, but often cherry-picking evidence to push your choice of language to your team is not a very good way to run your business. I actually generally dislike case studies like these, not because they aren't interesting, but because people use them as things that they can point to whenever they want to push their personal language agenda (I'm looking for a better word for this that isn't that negative, but until then I hope this comment makes it clear that I don't mean this in a "malicious, purposefully self-sabotaging" way).


You are making correct point. Most case studies are kind of lobbying effort to change opinion of decision makers. Sometimes it is done via developers instead of reaching to CIOs directly which Gartner quadrant does.

And I think this is all fine as long as people understand it is just opinion sometime of people who are more accomplished. Arguments occur when someone comes in and tell, how they language/Framework/technology is "objectively" superior other people's working solutions.


As a JS dev - the strength of a vertically integrated stack is high. I have a collaborative model editor which can run plugins on the model, and these plugins can be configured to run on the client or the server depending on what they do and what kind of requests they need.

This exact same language fuels my API and my client. It means I can share packages everywhere, and a problem solved once & put in a library is solved for the team

So, that said - I would also push back against introducing a new language into a stack which everyone shares knowledge of. What benefits did you propose that override such a thing? Or, conversely, why do the benefits I described above not apply to that team?


our JS build time was hovering around 30m for small changes. I built a proof-of-concept backend in go (basically a mirror of some existing services), and was able to build and deploy it in no time flat.

No one knew typescript at our org, but that was a much easier sell despite slowing down the build and HMR significantly.

It was not for lack of knowledge of go either; there were several developers on the team with strong go backgrounds.

Management was unsure of it as "new" technology despite using next.js, typescript. Really, they just were afraid of switching.

To your point about a vertically integrated stack, this is great in an small to medium environment but on a large (and quickly growing team) where the CI looks like a christmas tree and testing is sparse, it was actually quite difficult to manage. Maybe i'll muster up the courage to write a medium post one of these days.


Sounds like you're viewing Go as a silver bullet to endemic organizational issues here, and I find it hard to believe your assertion that Go is going to fix an engineering culture where "testing is sparse"


We tried to write tests, but they took too long to run. Also there was a great debate over which of the numerous testing frameworks to choose from? Chai? mocha? Cypress for end to end? How it all fits in the CI pipeline? For unit testing, go has a great built-in solution, and with testify you can get the rest of the way there.

I don't think go is a silver bullet solution, but when I see something I know can be a lot better and simpler, I generally tend to gravitate towards that.


It's funny, if you'd asked me almost a decade ago which language would compete with Go, I would not have answered "JavaScript"! Yet, these days I find that's the trade-off: build something "quick" in TypeScript that's easy to modify but perhaps a bit brittle and slow(er) to run in production, vs build something very considerate and optimized in Go but perhaps not something you can easily change without hiring folks specifically for the backend.

And then you've Java, which is now trying to be the "VM for every runtime" but is still best at Java itself, for now. I tried running JS-on-Java (graaljs) to improve the performance of JavaScript from "only twice as fast as Python" to "within the top 10 on TechEmpower" but found it had too many compromises to rely on it, it was just another runtime layer I would have to worry about.

I end up wondering if the solution really is to begin by prototyping efforts in slower-executing languages to start except where existing conditions and code ecosystems might allow for faster initial results in another language. (Kubernetes projects should likely use Go, etc.) Which is less about Go and more about the need to rewrite software later, I suppose.

Then again, these days the problems I end up spending (too much) time on are "which dependency should I use," or "should I rewrite the dependency," I rarely ask myself which language is "better" for a task because I end up having to use languages others are familiar with. Go is not yet universally one of those languages, but the more I see unfamiliar Go code in the wild, the more I feel it could be. One of its current strengths is that its simple syntax and maybe its repetitiveness also makes it quite easy to follow for newcomers.


I tried go and it's nice to work with. The use-case of when to with me is limited by other existing good choices.


I mean, it's hard to see Go as "very considerate and optimized" given the existence of modern, highly-efficient programming languages like Rust, D, perhaps Swift etc. It's obviously better optimized than JavaScript and its derivatives, or even Java/C#, but that's not saying much.


Rust doesn't have the stability yet that has been a bit of a double-edged sword for Go. And it's taken 5 years for Rust to get as far as it has. I'll be much more interested in using Rust in production when there's more of a "standard library" of options to start with. Right now it has the curse of being both unfamiliar to programmers and not having very many production-ready dependencies available in a larger ecosystem. It might be the "right choice" for the future, but if you don't already know you need Rust, I'm having trouble seeing how typical software can benefit today from Rust, etc., though I really do hope my answer changes over the next few years. :)

Swift is definitely something I'd like to explore more, but like Rust, it has few production-ready dependencies available. Kotlin or other Java derivatives on the other hand probably have too many -- if your code is written in Java, I've no idea if it will work great in Kubernetes or if it will expect OSGi or if it's a giant monolith. Which is to say, modern practices can make the JVM a surprisingly practical choice, but most software isn't really all that optimized -- slow and bloated legacy dependencies are both a problem in Java as in Node.js...

C# meanwhile can be efficient, but rarely is. And it has toolchain issues due to VS not being open source, and a very small ecosystem of dependencies, plus a history full of corporate rewrites of core functionality. It has a bright future, but its reliance on msbuild and Visual Studio limit it compared to Java. I'd like to suggest C++ but I've spent years learning it and find the complexity overwhelming in side projects. In practice, I think C++ is only appropriate for full-time projects with lots of engineers to validate correctness, etc. The exception I'd make is tiny C++ modules as glue code between languages, or to other existing C code.


Does C# rely on VS? MSBuild is separate from VS and you can use Rider (yay!) or VSCode instead of VS.

The ecosystem is definitely growing in the last 5 years too since open source has been embraced by MS and the community.

The major rewrite of .NET -> .NET Core and then now renaming it back to .NET again is good in that it's a much better framework now, bad in that it's turning out like Python 2 vs Python 3. Huge projects just can't upgrade, so old .NET Framework stuff is sticking around longer than it should.


Generally speaking, C# relies on either third-party implementations like http://www.omnisharp.net or Microsoft distributions, which on Windows is largely distributed via Visual Studio Downloads page, including the Tools for Visual Studio package: https://visualstudio.microsoft.com/downloads/ Are there other releases of msbuild, for example? Yes: https://github.com/dotnet/msbuild/releases But are they separate from releases of Visual Studio? No, as the release notes indicate. If you want to live on the bleeding edge of .NET development -- and I do recommend this -- you'll end up in the Preview channel of Visual Studio: https://visualstudio.microsoft.com/vs/preview/ and if you want to use Visual Studio Code instead, welcome to OmniSharp or similar "mostly compatible" solutions. It's totally fine until it's not, and it's definitely not portable or open enough -- yet. I look forward to the day when Visual Studio is fully open source because they can include subscriptions on top or something. That'll be the day when VS and VS Code could begin to merge a bit, at least for development on Microsoft platforms. But that hasn't happened yet, and they're rebuilding Visual Studio in Eclipse on other platforms to better support cross-platform development the same way Rider supports other platforms for JetBrains IDEs. It's a stop-gap until the fully-open-source versions of VS and VS Tools are finally available. I suspect they're waiting for .NET 5 or later, at this point...

They're undoing the split between Core and .NET Framework by suggesting that they'll ship both within .NET 5 using shims or implementations of drop-in replacements for .NET Framework code to use. Imagine if after dropping Python 2 support there was a mode that scanned for Python 2 code and enabled it again, on a file-by-file basis, to work with newer Unicode strings using some kind of translation layer in the runtime. That's kind of what's happening here, I think, but maybe more lightweight than suggested. Legacy .NET Framework code still deprecated, but interoperability libraries will ship as part of the runtime or SDK, will have some amount of shims available. I haven't followed the details closely enough to say more than this, though. I last looked into it a few months ago.


As far as I know - there will be those frameworks to select:

>net5.0

>net5.0-windows

>net5.0_something

So you can use "pure" "net5.0" on Linux and generally cross-platform software meanwhile still be able to use old .NET FrameworkX winforms/wpf on "net5.0-windows".


Go is pretty well optimized, for a garbage collected language, though of course it doesn't match up to a language without garbage collection. But much investment has been made in fast compile time and runtime simplicity, at the expense of some remaining potential performance gains.

While Java is generally slow, that's more the fault of Java developers and their FooDangleProviderModuleBuilderBuilderFactories. Due to runtime optimization Java can be nearly as performant as non-GC languages. In principle there are even scenarios where it can exceed the performance of any ahead of time compiled language.


It’s not reasonable to compare “optimization” between a zero-cost abstraction language like Rust and a GC-runtime language like Go. You write different programs in each.

There are idiomatic ways to avoid the GC in Go, and people do that in tiny places, but few people build ground-up that way, because it’s not the kind of program Go asks you to write.


Server-rendering React and puppeteer are the only two exceptions where I would pick nodejs over Go.


The good news is that this case study means you were probably right to bring it up as a worthwhile consideration, and you will have these case studies to point to next time.


nah, I just quit and started my own company instead. Now I use go on the backend. problem solved.


Does Google use Go for any non-server applications? For example in Android, iOS apps, ChromeOS, Chrome browser?


Quite an interesting question. The Android GPU Inspector[1] is a desktop GUI/CLI developer tool that's written mostly in Go, but also has a bit of client/server architecture internally so I don't know how you would count it.

1: https://gpuinspector.dev/


Go as a new language is a mega success.

K8s, docker, native concurrency, robust std lib, list goes on.

Obviously, not the magical swiss army knife for all engineering use cases, but successful in a lot of domains and well-liked by developers. Winning.

And its only version 1.XX.

I've never even used go and I am impressed.

Well done, Google. Well done. (golf clap)


> And its only version 1.XX.

Are there plans for a new version that is radically different, or is it going to be like Java or macOS where updates continue to change what is usually considered the minor version?



They will probably be introduced in a 1.x release and the design does not break backward compatibility. "Go 2" is an umbrella term for a couple of bigger features, some already released (e.g. Go modules and error wrapping), not a version number.


It also doubles as the name of a popular Eurobeat group ;)


No idea, but I think it is impressive that a language that is still on "version 1.XX" has been so successful so far.


Version numbers are fairly arbitrary. I use a lot of 0.x software that is basically run as a production release.


It's success is in part because of that, not despite it. Contrast with Python3, which alienated masses of users by making breaking language changes.


A project can use version numbers 1 ... 9999999 or version numbers 1.0 ... 1.9999999. The amount of work that goes into it is the same.


See for example Java, which basically dropped the 1. from 1.5 .


Not sure why it being version 1.XX is a factor here. Actually that's one of Go's features- compatibility.


Surprised Angular didn't make the short list at least angularjs.


Important point: this is Google's use of Go, not your use of Go. Take note to check whether their results are applicable to you before adding it to your repertoire of "reasons we should use Go at our company".


What are you trying to say?

Go is at my employer's (one of the top 3 car companies world wide) techradar the number one to adopt. New stuff of all kind is done in Go.

So, Go is a huge success outside of Google as well.

Not saying that I'm of any importance for Go, but I'm using Go for personal projects, at work for CLIs and standard backend stuff (APIs + DB, Redis, etc.) with great success.


I love reading about how companies use various technologies and how it works for them but I am personally weary of dealing with people who bring up these writeups in language wars without qualification–I'm sure you know the usual "Google uses it, so it must be good" or "Facebook stopped using it, so it must be bad" kind of proposition. Actually, I've written many words on the topic, many more than I have put there; perhaps you've seen it already ;)

But to be clear: I'm saying that reading about other people's experiences with a language (including yours here) is useful in making your own decisions, but you must also account for how you and your usecase are different than the one that was presented.


https://go.dev/solutions#case-studies

Link from the article

Honestly, it's not breaking news that Go is used heavily outside Google.


No, it's not, I was just talking about the article itself rather than the case studies from the past.


These are case studies from companies that aren't google.


Are they? I see links to case studies about Firebase and Google Cloud.


Are you looking at the right page? The first three companies I see there are American Express, Capital One and Cloudflare on the list they link to:

https://go.dev/solutions/#case-studies


I’m looking at the pages linked from https://opensource.googleblog.com/2020/08/new-case-studies-a..., which seems to be about Google’s use of Go.


> In the past year, we’ve posted sixteen case studies from end users around the world talking about how they use Go to build fast, reliable, and efficient software at scale.

Click on the link about the "sixteen case studies" and you'll see the rest.


Ah, sure. I didn't bring those up because they were older and not really directly part of this submission.


Kinda tired of the proliferation of languages coming out of Google, whether they actually created them or not.

If Go is so great, why was Kotlin released four years later and made the standard on Android? It's annoying enough to have to use Swift and Kotlin for iOS/Mac vs. Android. Now Go? What happened to Dart?

Then there's Rust. What about next week?


> What happened to Dart?

Dart is one of the three officially supported and approved languages of Fuchsia.

https://fuchsia.dev/fuchsia-src/contribute/governance/policy...

The only language that came out of Google that people have a right to be upset about is PromQL. That's an abomination.


Different use cases.

Golang is made for simple deployments, mostly services that need to scale, stuff you'd previously had to use something like C++ or Java for.

Dart is mostly relevant if you're building apps with Flutter.

Kotlin isn't Google's creation, they just recommend it for developing native Android apps instead of Java.


If you're really wondering why different programming languages exist, the answer is simple: different use cases, and the influence of past languages. Bell Labs did the same by creating C, C++ and AWK.

For any of the languages you mentioned, it's easy to find the motivation for their creation, either by Wikipedia or on official pages Why X?. Your uninformed rant sounded a bit lazy and naive (sorry, no offense intended).

From the top of my head... Go was meant as a higher-level language than C where Python could not apply (bad performance, weak typing, no compilation, complex syntax); its wide adoption proves that kind of language was missing at the time. Dart was initially meant as an alternative to JavaScript, like CoffeScript, at a time where JS was less standard. Kotlin was not created by Google, and was meant as a light alternative to Java/JVM, with full compatibility, hence the adoption for Android which is JVM based. As far as I know, Swift and Rust aren't specifically tied to Google.


Google didn't make Kotlin or Rust o_O


Kotlin is from JetBrains, not from google


also interesting go is not an approved language on google's fuschia


[flagged]


Whatever your opinion of the user-facing features of Google, it is true that you would not have access to most of them if Google didn't have deep skills in large-scale systems programming which allows them to whip up products that nobody else could afford to offer. How do you think they are able to offer infinite jpeg storage to every human, for free?


> infinite jpeg storage to every human, for free?

How does one get free infinite jpeg storage from Google? Way back when I had Picasa and I'm 90% sure there was a paid tier. I recall hearing something about Google offering free image storage to Google Pixel owners but that is a far cry smaller number of people than "every human" and the purchase price of a Pixel device isn't free.


> How does one get free infinite jpeg storage from Google?

Store your images at photos.google.com. It is a free service with unlimited storage quota.


I think it's unlimited only if you allow google to resize your images and not maintain them in the original resolution/quality.


Ah, I see now. Google will store an unlimited number of photos that they compress to "High Quality" and it is limited to 15 GB uploaded per day. There is a storage limit on the "Original Quality" images (e.g. images not put through Google's compression).

Reminds me of the Linus Tech Tips video where they try to use Google's claim of unlimited free storage to backup their video library to Google Drive [1]. Eventually Google rate limits their access so harshly that it becomes a practical limit.

Just like those "unlimited" mobile data plans that eventually slow down your service it is really just marketing. They hide the actual limits but they are there to prevent abuse.

1. https://www.youtube.com/watch?v=y2F0wjoKEhg


Google Translate, for example, is amazing.


Eh. I enjoy the variety of languages of GT, but the quality is (imo) better with DeepL[1], and Yandex Translate[2] has some minor languages of Russia and ex-USSR which either aren't supported by Google or aren't supported on the same level. E.g. Bashkir and Mari. GT is still very impressive, don't get me wrong. But it has some strong competitors.

[1] https://www.deepl.com/translator

[2] https://translate.yandex.com/


Thanks, didn't know good alternatives existed.


Google Translate produces mediocre results with European languages and absolute gibberish with Chinese or Japanese.

Personally, Google Translate is my litmus test for "is ML actually any good". If we ever reach the point of fluent translation of German or coherent translation of Japanese, I will be extremely impressed.


Automatically producing mediocre results is amazing.

So: Google Translate IS amazing. The result of Google Translate is definitely not amazing, but that wasn't the claim.


You mean a neural network I could pull off github, and if I had enough money to train it, end up with the same results?


You do know that they designed the NN they trained as well as collected the data set, right?

We aren't to the place where a single individual with enough compute resources could feasibly replicate google translate.


Seems fairly off topic


I think it is on topic. I’m tired of this company parading their “technical achievements” while simultaneously constraining humanities access to information


Your second statement is a good reason to complain about Google if properly substantiated, but it still is very tenuously linked to developing and promoting Go


I see why go is clearly superior to C++. I see why it's simplicity is great for bringing new people up to speed. I see why it's concurrency model is better than many other languages. And I really like their software engineering philosophy.

Go seems clearly one of the if not the best systems language around.

But how is Go in the line of business web application space? The space that's historically been dominated by your Python, Ruby, Go , node.js, C#, Java applications?

I get it's probably more performant, but honestly in C# my primary language I spend almost all my time optimizing DB queries and almost none optimizing C# code. I get it's concurrency model is better, but with web apps that usually isn't much of a problem.

Is Go as better in this space as it clearly is in the systems programming space? I get it could be used for the LoB use case but is it better, and if so is it significantly or marginally better?


> I see why go is clearly superior to C++.

You shouldn't. If anything you should be looking into where C++ does better than Go and see if Go is improving there–and understanding that there will always be places where Go is not the best choice or even appropriate.


I'm sure Go is not better for every single use case. But it seems to be there were a lot of high performance systems that would have been written in C++, like InfluxDb for example that are clearly more reliable and easier to develop because it was written in Go.

Where do you think C++ outshines Go?


I think that's an example of a system where the performance demands weren't high enough to justify using C++. There are lots and lots of applications where the overall architecture can't take advantage of the speed of C++, but I think there's no question that the peak performance of C++ far outshines the abilities of Go.

Taking an example from the article, parts of Google's indexing pipeline are now in Go, but nobody is suggesting that the search engine would be.


Go is basically almost as fast as C++.


And cat food is "basically" pâté. The Go toolchain lacks virtually all of the optimizations that a C++ compiler would employ in an optimized build and the Go toolchain also lacks all of the ways you'd achieve peak optimization for C++, such as profile-guided optimization and link-time interprocedural optimization.

These programs are are not even peak optimized but the C++ version still wins every case by between 10% and 1000%.

https://benchmarksgame-team.pages.debian.net/benchmarksgame/...


Performance, as 'jeffbee mentioned, but it's also great for low-level systems programming, has multiple high-quality implementations, powerful compile-time features, and can interact particularly easily with mountains of already existing C and C++ code.


I think you might have bad information. Go is not a systems programming language. You may be thinking of Rust? Go and C++ serve very different needs.


You're being downvoted, but you're correct. Go and C++ have largely different non-overlapping use cases. Go is not a systems language. It's mostly a networked server language with a garbage collector. It's great for writing a wide variety of networked services like HTTP app servers. C++ is great for when you need full control and best possible performance and are willing to pay the hits in complexity, compile time, and other development expenses to achieve that. Drivers, games, trading software, database engines, etc.


I think I only agree with you on games and trading software. In games, you have 4ms (assuming an esports game at 240Hz) to read input, read game state from the network, do all your simulation, draw a frame to the screen, and write the results back to the network. There is absolutely no time budget for anything else; in fact, C++ games don't even manage to run at a 240Hz tickrate and just hack around the input / display handling while they wait for 60Hz networking and simulation run in another thread. (Going off topic, the end result of all of this is an incredible example of what "eventual consistency" means in the real world. Play a multiplayer FPS and you'll never use a database in any mode other than strict serializable again.)

For drivers and database implementations, there is more time to do stuff. For example, I wrote a keyboard controller with Tinygo, and it mostly sits around waiting for the USB host's C++ driver to ask it for data. Go isn't adding any latency (and it's not really C++'s fault either; the standard sets a time interval to poll at). And if you wonder what an OS written in Go would look like, look at gVisor. It's not technically an OS, but it does a large number of OS-like things.

Database engines that are focused on throughput rather than latency will also do fine with an occasional GC delay. CockroachDB and InfluxDB have plenty of users.


I think GC is not harmful than helpful in drivers and things like an OS. gVisor in particular jumps through hoops for performance and still has poor performance. It could be more successful in C++ or Rust probably.

I like Go a lot, but if you needed the performance or manual control it is not the tool for the job. On the other hand most problems don't fit that description and Go is one of the best choices for them.


I think a lot of people just assume there's a ton of overlap because Go is AOT compiled into a single binary (like Rust and C/C++). As silly as that is.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: