Personally I just far prefer to work in a GCed langauge. Much simpler mental model.
That's the requirement for 100% if professional software development.
"The key point here is our programmers are Googlers, they’re not researchers. They're typically, fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They're not capable of understanding a brilliant language but we want to use them to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt."
And interpreting the quote charitably I'm going to have to agree with it - I don't think many of my coworkers care enough to get to the point where they'd appreciate everything something like Haskell can do for them.
Most programmers are "lousy programmers" because most of the are not researchers and have no interest in theory.
I can write in Go or Rust (or anything else given some time) but I won't ever use Rust to write any kind of business logic for my company - and this is what I do most of the time I actually write code.
Why? Because Rust is terrible for the job (at least if we are talking about real life scenario where the job should be done in hours and not weeks)
but this would be a problem almost anywhere, no?
This has nothing to do with Rust vs Go vs Ruby or something else. Rust makes this even bigger problem, ok, but I don't think we should call people not using Rust (c\c++ etc) "lousy".
PS: tbh this kind of statements usually (from my experience) come from people who mainly write system level software or work with hardware directly.
That is exactly how it was sold.
A safe C, or a nicer simpler Java.
Nobody cared about Erlang back then and nobody does today.
I write Erlang for a living.
It's never been "safe C" because it's garbage collected. Java is truly the comp because it's a great Grug language.
I also wrote some Erlang in the past, I really enjoy it and I was sad that Go didn't borrow more.
Nobody may have known they cared about Erlang, but those features sure made people pay attention.
I think this is incredibly correct and obviously personally true for you but I'd like to add one more thing from the peanut gallery.
No one really needs Erlang either. Turns out most problems are just fine not being modeled in the way that Erlang wants to model problems.
Not that I think Erlang manages to be a nail gun; it has enough idiosyncrasies that the comparison is not terribly accurate. Still, “need” is doing a lot of heavy lifting in that sentence.
Yeah it was a bit vague -- I should have said something more like "not many developers/teams/companies need telecom level uptime and resilience enforced at the single system level". In reality, most groups have solved this by redundancy and building multiple systems/distributing them. You could argue it's the wrong solution, but it's been good enough for so many people that... it's probably fine.
Ironically, Java was sold as a "nicer simpler C++".
Go's selling points are different: it takes a weekend to learn, and a week to become productive, it has a well-stocked standard library, it compiles quickly, runs quickly enough, and produces a single self-contained executable.
I would say that Go is mostly a better Modula-2 (with bits of Oberon); it's only better from the language standpoint because now it has type parameters, but GC definitely helps make writing it simpler.
A lot of very smart stuff is written in Go by programmers who just want the language to get the hell out of their way. Go is some ways very good at that. Rough though if you want your programming language to model your problem domain or your algorithmic approach! TANSTAAFL.
Having used go in anger I don’t necessarily agree with this, could you point out an example. Maybe I just accepted it and work around it without paying much attention.
If you are referring to interface types being able to be null, well they are allocated on the heap and have dynamic dispatch, this isn’t particularly a surprise if you have worked in a lower level language but might be a surprise if you come from a language where that isn’t the case.
> Please don't post shallow dismissals, especially of other people's work. A good critical comment teaches us something.
I'm curious to know why you think so, I thought it was a great article, showcasing how simplicity in the language doesn't make complexity go away, it just moves it to programs written in it.
And the related read is purely a misunderstanding about how concurrency is modelled. Channels are not meant to be written from multiple writers, maybe this gets discussed in the next article. I can understand why it is confusing and you consider it unintuitive.
The read situation is literally not understanding or even looking up the interface, there is another return value that will tell you the channel is closed.
Nil channel reads make sense for it to do what it does if your familiar with the interface but at the same time you are literally holding it wrong. Vs a language where that would be UB its an improvement. Compared to a language like rust sure the information isn’t available at compile time but on the same not you would need to be developing in rust, and no offence but if you think golangs concurrency story is difficult to grasp just wait until you meet async rust…
These are the unintuitive, these are generally complaints of you failed to even begin to read the documentation and then complain when things aren’t doing what you expect, leave your preconceived notions at the door and you will be fine.
The faster than lime take needs to be updated, comparing golang from 5 years ago to modern golang is about as useful as comparing rust fron 5 years ago to rust now.
And you can happily make Cgo calls to the windows libraries if you want to access windows APIs, the language provides an abstraction for the normal use case not the specific use case, theres an escape hatch if you want it. And regarding the complaint about timeouts, context is a thing.
Because you don’t know how doesnt mean it’s unintuitive, it means you don’t know how.
Not having to call into ffi/c libraries to modify files is the normal use case. Windows is the largest used operating system.
> Because you don’t know how doesnt mean it’s unintuitive,
Do you know what the definition of unintuitive is? If it was intuitive you wouldn’t be able to “hold it wrong”.
A “systems” language designed by some smart people that is mostly targeted at the most deployed os in the world “cough not windows”, definitely does not need to make windows the default.
> If it was intuitive you wouldn’t be able to “hold it wrong
No unintuitive means if you understand the domain and idioms yet the interface still does not make sense. Returning multiple values when reading and passing context around (even in a wrapper) is normal intuitive golang.
So is allocating complex object instead of simply instantiating them, sure this point is slowly moving out of idiomatic golang but at the same time the history is important.
Not understanding CSP and not liking explicit return values does not mean it is unintuitive.
I can see this conversation will go no where though. This is the typical conversation with Go users when you point out any criticism of the language. Cheers man.
You don’t. Normal operation like reading writing modifying and creating works just fine in windows.
The only thing that doesn’t is explicitly permissions where windows is the outlier and uses (imho a better) method of managing permissions. However they are the outlier and it is an uncommon operation. Why would the stdlib cater for that?
If you need to alter permissions at a more granular level on windows than is possible using golangs interface then call into the ffi, but in general you don’t need to to that.
If that is your only criticism then I agree we will not agree on this point, it is however also trivial to make ffi calls using go
Of the few technical advantages Go had for us is that we don't need a single dependency outside of the standard library, which can't live in isolation. We use SQLC and Goose, both are run in containers that only have rights and access on the development side of things.
I'm not sure I would say that Golang has a lot of weird, pointless quirks, but it has opinions and if you happen to dislike them, well... that sucks. I hate the fact that they didn't want runtime assertions as an example, so it's not like I don't understand why people dislike Go for various reasons. I've just accepted that those strong opinions is the reason Go is so productive.
The challenge for us is that it's not exactly as productive as Python. So while you'll need to do a lot of toolchain work to get Python anywhere near Go's opinionated stucture, that is often a better choice if you're not a hardcore software engineering team. At least for us, it's been much easier to get our business intelligence people to adopt UV, pyrefly, ruff and specific VSC configs for their work than to have them learn Go.
I suspect that is why Rust is also doing so well. Go is a better Java/C# for a lot of places, but are you really going to replace your Java/C# with Go if you have dacades worth? If you're not coming from Java/C# will you really pick Go over Rust? I'm not sure, but I do know, Go failed to become a Python replacement for us. It did replace our C#, but we didn't have a lot of C#. Eventually we'll likely replace our Go with C/Zig and Python to keep the language count lower.
So you hate writing:
if (something != 1) {
panic("oh no!")
}
vs assert(something != 1, "oh no!")
? Reminds me of people complaining about Python's significant indentation. If that's what you're complaining about, you have nothing to complain about.You're taking it out of a context of me praising Golang, however, and while I do hate the fact that they didn't just do runtime assertions, it's not like I dislike Go as a whole because of it.
So compared to... very niche languages? Go has exceptionally few quirks compared to mainstream languages.
This isn't meant to be allegorical or anything specific. I guess it's just an observation that sometimes your lunch can be cheaper than you thought.
Rust is more appropriate for areas where the problem boundaries are relatively fixed and slow-moving: libraries, backend services, and infrastructure.
By better allowing you to model your program domain, Rust actually lets you finish projects that are feature complete. I have multiple Rust projects in production for years that have needed at most one or two bugfix releases after their initial rollout on top of a half a dozen feature updates. For a very slight additional startup cost in doing that modeling, I’ve gotten massive dividends back in the volume of maintenance programming that hasn’t needed to be done.
But if your problem domain changes frequently enough that the model needs to be changed all the time, that extra inflexibility isn’t worth it. On the other hand, I don’t know much go software that isn’t beset by the same number of bugs as every other modern language.
There are numerous interviews with Rob Pike about the design of Go from when Go was still being developed, and Erlang doesn't come up in anything that I can find other than this interview from 2010 where someone asks Rob Pike a question involving Erlang and Rob replies by saying he thinks the two languages have a different approach to are fairly different:
https://www.youtube.com/watch?v=3DtUzH3zoFo
It's at the 32 minute mark, but once again this is in response to someone asking a question.
Here are other interviews about Go, and once again in almost every interview I'd say Rob kind of insinuates he was motivated by a dislike of using C++ within Google to write highly parallel services, but not once is Erlang ever mentioned:
https://www.informit.com/articles/article.aspx?p=1623555
The point of my comment is that to say that Go is basically Erlang style CSP without the weird syntax is not justified as an actual quote nor as a paraphrasing or summary of anything that anyone involved in the design or promotion of Go has ever said. It's best to reserve quotes for situations where someone actually said something or as a way to summarize something for which there are ample references available.
One should not use quotes as a way to present mostly original claims that are presented as if it's some kind of already well established knowledge.
And performant enough.
Engineers ship with them, and do not care if there’s a purer system elsewhere.
I think channels have too many footguns (what should its size be? closing without causing panics when there are multiple writers), thus it's definitely better "abstracted out" at the framework level. Most channels that developers interact with is the `Context.Done()` channel with <-chan struct{}.
Also, I'm not sure whether the go authors originally intended that closing a channel would effectively have a multicast semantics (all readers are notified, no matter how many are); everything else have pub-sub semantics, and turns out that this multicast semantics is much more interesting.
Non-buffering channels are much simpler to reason about and have very useful semantics in pipelines.
Are these people here in the room with us right now?
Go is like C but with concurrency/strings/GC/a good stdlib
Go is like C++ but simpler/fast compilation/no generics/a good stdlib
Go is like Python but statically typed/multithreaded/fast/single executable
Go is like Java but native/no OO
---
One thing Go haters rarely reckon with is that Go is the only popular modern language (ie from this millennium). Everything else is way older. Well, I would actually say that this is probably the cause of Go hate--if it weren't popular no one would care.
This requires you to squint so that "popular" happens to identify only a handful of languages but conveniently catches Go and not say Swift or Rust. It's not difficult to do this, but it's not very honest to yourself.
- TIOBE [0]: Go 7 :: Rust n/a (> 10)
- IEEE Spectrum [1]: Go 8 :: Rust 11
- Stack Overflow [2]: Go 13 :: Rust 14 (they're pretty close here)
- GitHub [3]: Go 10 :: Rust n/a (> 10)
- PYPL [4]: Go 12 :: Rust 10
- HackerRank [5]: Go 8 :: Rust n/a (> 13)
- Pluralsight [6]: Go 9 :: Rust n/a (> 10)
- Redmonk [7]: Go 12 :: Rust 19
Although I admit we probably don't have great measures of this, there's clearly a sizable gap here.
Maybe you'd want to argue about TypeScript, Swift or Kotlin? I consider TypeScript JavaScript (because TypeScript wouldn't be popular unless all JavaScript programs were TypeScript programs), and I think Swift and Kotlin only survive because of their mobile platforms (they're also all below Go in these lists, on average).
[0]: https://www.tiobe.com/tiobe-index/
[1]: https://spectrum.ieee.org/top-programming-languages-2024
[2]: https://survey.stackoverflow.co/2024/technology
[3]: https://github.blog/news-insights/octoverse/octoverse-2024/#...
[4]: https://pypl.github.io/PYPL.html
[5]: https://www.hackerrank.com/blog/most-popular-languages-2024/
[6]: https://www.pluralsight.com/resources/blog/upskilling/top-pr...
[7]: https://redmonk.com/sogrady/2025/06/18/language-rankings-1-2...
The claim made was "Go is the only popular modern language (ie from this millennium)"
That's a binary, either a programming language is "modern" (from this millennium) or not and either it is "popular" (undefined) or it is not, Go is popular and modern according to the claim.
On your lists you find Go is anywhere from 7th to 13th in popularity. So apparently "popular" might mean 9th like Ada on TIOBE's list right? Or maybe "modern" includes Typescript, on several of these lists?
No, the whole contrivance is silly. Go is a relatively popular modern language, nobody is surprised to discover that. Is it the most popular? No. Is it the most modern? Also no.
>> This requires you to squint so that "popular" happens to identify only a handful of languages but conveniently catches Go and not say Swift or Rust. It's not difficult to do this, but it's not very honest to yourself.
> You seem to be arguing that Go is more popular than Rust, but that's not what we're talking about.
Isn't this exactly what we're talking about? I don't think you have to squint too hard to invent the gap between Go and Rust (et al).
> So apparently "popular" might mean 9th like Ada on TIOBE's list right?
No because it's only on that list.
> Or maybe "modern" includes Typescript, on several of these lists?
No because TypeScript is JavaScript, which is from the last millennium.
> No, the whole contrivance is silly.
Emotionally I agree with you, but in practice you gotta pick a stack, and there's a lot of benefit to choosing Go over Rust/Kotlin/Swift/TypeScript/Java/C#/C/C++/Ada.
> Go is a relatively popular modern language, nobody is surprised to discover that.
Eh I'm making the Stroustrup "there's two kinds of programming languages" argument. IMO, at this point Go criticisms are just jeers from the cheap seats.
So, if you don't count the lists where it isn't in the top ten, and you don't count languages like Typescript? Does that feel like an important distinction to you with the exceptions, rather than an arbitrary post doc justification ?
> Isn't this exactly what we're talking about? I don't think you have to squint too hard to invent the gap between Go and Rust (et al).
Likewise for Go and Python or Javas, so why the "top 10" ? Arbitrary.
> TypeScript is JavaScript
No. Javascript is (very bad) Typescript, but Typescript is not Javascript. That's why they have a transpiler.
If you contend that the similarity means they're the same language that makes C++ also C and I don't think you want to start that fight.
My pithy response to the Stroustrup argument is a T-shirt I own which says "Haters gonna make some good points". Yes of course people will criticize your popular language, but this observation does not make the criticisms untrue, and resorting to Stroustrup's argument is best understood as an admission that he has no response to the actual criticism.
C++ is remarkably bad. You're looking at popularity lists. What else is on those lists which has similar levels of criticism? Go is a long way short of perfect but it's nowhere close to C++. If Go is the Stallone "Judge Dredd" then maybe C++ is "Batman & Robin".
I feel like we both understand each other at this point so I'll ask because I'm curious, what languages are you into? I'd really like a chance to dig into Erlang, OCaml, or Racket, but I can never really justify it. Mostly I'm a boring C/Python person (believe it or not, I don't like Go all that much)
I currently get paid to write, among other things, C#, Python, PHP, Perl, and bash. Historically I have also been paid to write C, Java, and Go, among other things.
In contrast "Batman & Robin" is terrible. Clooney said he didn't want friends and family to see it because he is rightfully ashamed to have done it. Sometimes an actor does good work but it's hard to see because the technicians are incompetent and the editor destroys their effort in the cut - however it's clear Clooney was not trying.
Alicia Silverstone has been in utter trash, some of which I have watched because I used to live with a guy who was obsessed with her - but it's notable that even the icky "technically this isn't pornography" stuff she did as a teenager is more competent than "Batman & Robin" for which she was presumably much better paid.
Joel Schumacher can do excellent work so why is "Batman & Robin" so awful? Did the Studio tell him nothing else matters so long as the branding is there because comic book fans will show up anyway? If so maybe it's partly their fault, but a good artist should have more pride in their own work than to do this.
I have more recently (well, this century) gone to a "live MST3K" type event where they screen the original film but talk over it. They warned us that "Batman & Robin" is too awful for this format to save it, but I didn't listen and yeah, long before the closing credits lots of people walked out because they were right and it's unsalvageable.
I actually lived near a movie theater that got bought out by someone very weird and ostensibly rich, and they just played bad movies to jeer at and mock, and every... Friday was Rocky Horror Picture Show night. I think the small town I was in revolted and raised money to then buy that guy out, but man what a time. Surprised they didn't screen this steamer lol, is all I'm saying.
How do you figure Swift is not a general purpose language ?
Rust. TypeScript. Swift.
28.0M JS+TS
...
5.6M Swift
5.1M Rust
5.0M Go
They have measured Rust growing faster than Go over the years, with the overtake finally happening in Q1 this year.There aren't a lot of reports presenting absolute numbers and not biased toward a handful of platforms or ecosystems. If you know of other good free ones, feel free to share.
https://research.slashdata.co/reports/6814fddffed4a97023eab0...
EDIT: also I gotta say these numbers seem kinda high. It's hard for me to imagine there's ~28m JS programmers worldwide; that's 1/286 people in the entire world, and the ratio gets less believable as you shrink down the number of people who might have any access at all to a computer/internet/etc. Unless this definition is super broad, I'm quite skeptical.
But golang/newsqueak was developed much earlier, in the early 80s by Rob Pike.
https://en.wikipedia.org/wiki/Newsqueak
```
type point: struct of{ x, y: int; }
a:=mk(array[10] of int) // mk renamed to make
select{ case i = <-c1: a = 1; case c2<- = i: a = 2; }
```
In the late 2000s, this language updated somewhat (for example, the mk function was renamed to make).
Stackless coroutines are even more efficient for that case, and Rust makes them comparatively easy. (And slated to get even easier in future versions, as the async support is improved further.)
Moreover stackful coroutines/fibers as used in Golang also makes it infeasible to have seamless FFI with the standard C API/ABI, which cuts you off from the bulk of the ecosystem. There are other issues too with having fibers in a C-like systems programming language - see https://www.open-std.org/JTC1/SC22/WG21/docs/papers/2018/p13... for a nice summary of them.
The plan9 libthread (which reimplemented the Alef concurrency model for C) did have seamless use of the C API/ABI.
The mechanism was that it had threads and coroutines, a function needing to make use of the C API in a seamless manner would simply run as a thread rather than a coroutine. It was then easy to share data as the CSP model (with channels) worked between both coroutines, threads, and coroutines within a thread.
So if one wishes to use stackful coroutines, and still have that seamless compatibility, an approach mixing the Go and Alef approaches would seem necessary. i.e. the Go migrating coroutines as a default, but with the option to use Alef like thread bound coroutines when necessary.
This reintroduces the colored functions that we were trying to get away from in the first place, by adopting stackful coroutines/fibers. Why not use async at that point? I can understand that Alef didn't, because stackless mechanisms were not well understood at the time. But it's plausible that we can do better.
In micro-service world there are many service which read request over the network (HTTP or some RPC), send multiple requests, may be read something from disk, write logs all mixed with some business logic. A significant fraction of time is spend on waiting so a single modern server can handle a large number of parallel connections to the service without saturating hardware resources.
Async allows to do the same (handle many network connections in a single thread) but: 1. It's less ergonomic (less easy to write code) IMHO 2. In pure async if you do a long CPU intensive task in between I/O all other connections in the same thread will wait, which Go solves (at least partially) by using M:N model (pure async is M:1 - connection tied to a particular thread and even if you have many threads you cannot move connections around).
I would not argue that Go concurrency model is the best we can get but it's a good fit for micro-service architecture and a good balance between performance and easy development.
> Linux doesn't even allow you that many file handles.
Not by default but it's easy to rise limits for this and if you are running a loaded server you should not rely on defaults anyway. To get to 100M descriptors you likely need to tune only ulimit (LimitNOFILE in systemd) because default value for fs.file-max is likely large (AFAIR default scaled to the RAM size).
Which is ironic, maybe kinda funny. The first "larger" project I've tackled in Go was a chat server. I wanted a simple supervisor for each connected client; in case a goroutine encountered a recoverable error but needed to be restarted. I don't have any practical experience with OTP, but I've always been a big fan of daemontools/runit/etc: just let it crash, restart, and recover.
So in Go, you can't (easily) obtain a handle to a goroutine. The authors' entire argument seemed to be that this would allow developers to implement "bad" patterns, like thread-local storage. You can of course still come up with some wrapper code, like this:
type Service struct {
err <-chan error
run func(*Service)
}
s := &Service{err: make(chan error)}
realRun := func() error { ... }
s.run = func(s *Service) {
s.err <- realRun()
}
go s.run(s)
err := <-s.err
But what you really wanted was something like: run := func() error { ... }
g := go run()
err := <-g
Now of course you still want some wrapper code to maintain client/connection state, etc. But if you wanted a "real" supervisor tree, you'd have to do this dance for every sub-goroutine you'd like to spawn. You'll soon end up with func(*Service, any) and throw away static typing along the way. Generics wouldn't be introduced until 18 releases after, and I don't think they would help all that much.Correct me if I'm missing anything obvious.
While I like the language, threads in Go are not any easier than any other language (which is to say, most devs can't use them correctly, and your program will have bugs), and suffer from a ton of ergonomic issues, like being hard to keep track of, difficult(ish) cancellation(how do you cancel a big synchronous I/O operation), and channels suffer from backpressure related hard-to-debug issues.
They are though. Even Java people agree, Java recently got their implementation of goroutines (green threads). It's a superior model to async for application level programming.
Immutability is the actual core and power of Earlang
I don't think this is a bad thing but it's a funny consequence that to become mainstream you have to (1) announce a cool new feature that isn't in other languages (2) eventually accept the feature is actually pretty niche and your average developer won't get it (3) sand off the weird features to make another "C but slightly better/different"