any downsides to it in your experience?
Others have mentioned the main issues, but to add; you often end up writing “ugly” code to do basic concurrency operations. Often setting up channels or workgroups then a `go func {}(…); wg.Wait();` just feels wrong and makes you thing “I must be doing something wrong, there must a better way, but that’s IS the way. It’s just go syntax quirks at the end of the day, and makes you appreciate go’s simplicity over high abstractions.
In my experience the main hurdle was getting developers on the team onboard with go’s way. It felt like swimming upstream for my 6 year stint in go. I was in a very Java heavy “enterprise” but we were writing a kubernetes operator and I pushed to use golang because (a) I liked it, and (b) it was 2019 and the entire kubernetes ecosystem was primarily go.
To me golang was very simple and I drank Rob Pike’s and Google’s narrative of how easy it’s to get a competent “compute science major in college”-person to pick up go. What I experienced was a form of “you can’t teach an old dog new tricks”. Lazy (and I hate to use this word) developers who gotten so used to frameworks and IDEs doing all the heavy lifting for them in Java or C# had 0 appetite forgetting all the questionable patterns they learned over the years and adopt Go’s simplicity. It was very frustrating at time, yet gave me a good eye for the actual skilled talent in the organization vs the average enterprise developer persona.
It's not memory safe: https://www.ralfj.de/blog/2025/07/24/memory-safety.html
Go and Julia are fun languages.
In production, Go has proven solid for several years. It is best when used with the native code people ported.
There are only two issues I encountered:
1. getting the legacy ancient C source meta-circular Go compiler working to port the Go boot-strap compiler upgrade chain is a kick in the pants. However, once it is on a architecture it has proven rather resilient.
2. memory limited systems can develop reliability issues, as Go programs will often ungracefully throw hard to diagnose unrelated errors during each crash. A good metric is 3:1 of your average load as a safety margin (if you see 2GiB in average RAM use, make sure to over-provision the host with 8GiB RAM etc.)
Other than the above short list of edge cases, if you join a pure Go project it is usually pretty reliable. Most community folks interested in the language seem fairly competent at building stuff that is fun. =3
Managing channels and making sure they are closed just once is quite messy compared to other languages. The Go channel axioms[1] don't make much sense: why does closing a channel multiple times panic, but reading from a closed channel returns a zero value?
Kotlin gets this right. On send/receive, you can use trySend or tryReceive if you want to avoid exceptions. Considering Kotlin also has coroutines and structured concurrency, concurrency in Kotlin feels more ergonomic to me than Go. At least if you want to get concurrent code with least amount of bugs and not just least amount of extra keywords.
[1] https://dave.cheney.net/2014/03/19/channel-axioms