I've been using Go more or less in every full-time job I've had since pre-1.0. It's simple for people on the team to pick up the basics, it generally chugs along (I'm rarely worried about updating to latest version of Go), it has most useful things built in, it compiles fast. Concurrency is tricky but if you spend some time with it, it's nice to express data flow in Go. The type system is most of the time very convenient, if sometimes a bit verbose. Just all-around a trusty tool in the belt.
But I can't help but agree with a lot of points in this article. Go was designed by some old-school folks that maybe stuck a bit too hard to their principles, losing sight of the practical conveniences. That said, it's a _feeling_ I have, and maybe Go would be much worse if it had solved all these quirks. To be fair, I see more leniency in fixing quirks in the last few years, like at some point I didn't think we'd ever see generics, or custom iterators, etc.
The points about RAM and portability seem mostly like personal grievances though. If it was better, that would be nice, of course. But the GC in Go is very unlikely to cause issues in most programs even at very large scale, and it's not that hard to debug. And Go runs on most platforms anyone could ever wish to ship their software on.
But yeah the whole error / nil situation still bothers me. I find myself wishing for Result[Ok, Err] and Optional[T] quite often.
xyzzyz · 18m ago
Go was designed by some old-school folks that maybe stuck a bit too hard to their principles, losing sight of the practical conveniences.
I'd say that it's entirely the other way around: they stuck to the practical convenience of solving the problem that they had in front of them, quickly, instead of analyzing the problem from the first principles, and solving the problem correctly (or using a solution that was Not Invented Here).
Go's filesystem API is the perfect example. You need to open files? Great, we'll create
func Open(name string) (*File, error)
function, you can open files now, done. What if the file name is not valid UTF-8, though? Who cares, hasn't happen to me in the first 5 years I used Go.
koakuma-chan · 10m ago
> What if the file name is not valid UTF-8
Nothing? Neither Go nor the OS require file names to be UTF-8, I believe
nasretdinov · 11m ago
Note that Go strings can be invalid UTF-8, they dropped panicking on encountering an invalid UTF string before 1.0 I think
xyzzyz · 9m ago
This also epitomizes the issue. What's the point of having `string` type at all, if it doesn't allow you to make any extra assumptions about the contents beyond `[]byte`? The answer is that they planned to make conversion to `string` error out when it's invalid UTF-8, and then assume that `string`s are valid UTF-8, but then it caused problems elsewhere, so they dropped it for immediate practical convenience.
kace91 · 5m ago
My feeling is that in terms of developer ergonomics, it nailed the “very opinionated, very standard, one way of doing things” part. It is a joy to work on a large microservices architecture and not have a different style on each repo, or avoiding formatting discussions because it is included.
The issue is that it was a bit outdated in the choice of _which_ things to choose as the one Go way. People expect a map/filter method rather than a loop with off by one risks, a type system with the smartness of typescript (if less featured and more heavily enforced), error handling is annoying, and so on.
I get that it’s tough to implement some of those features without opening the way to a lot of “creativity” in the bad sense. But I feel like go is sometimes a hard sell for this reason, for young devs whose mother language is JavaScript and not C.
guappa · 23m ago
> The type system is most of the time very convenient
In what universe?
theshrike79 · 14m ago
In mine. It's Just Fine.
Is it the best or most robust or can you do fancy shit with it? No
But it works well enough to release reliable software along with the massive linter framework that's built on top of Go.
theshrike79 · 11m ago
People tend to refer to the bit where Discord rewrote a bit of their stack in Rust because Go GC pauses were causing issues.
The code was on the hot path of their central routing server handling Billions (with a B) messages in a second or something crazy like that.
You're not building Discord, the GC will most likely never be even a blip in your metrics. The GC is just fine.
traceroute66 · 13m ago
> Just all-around a trusty tool in the belt
I agree.
The Go std-lib is fantastic.
Also no dependency-hell with Go, unlike with Python. Just ship an oven-ready binary.
And what's the alternative ?
Java ? Licensing sagas requiring the use of divergent forks. Plus Go is easier to work with, perhaps especially for server-side deployments.
Zig ? Rust ? Complex learning curve. And having to choose e.g. Rust crates re-introduces dependency hell and the potential for supply-chain attacks.
theshrike79 · 9m ago
uv + the new way of adding the required packages in the comments is pretty good.
you can go `uv run script.py` and it'll automatically fetch the libraries and run the script in a virtual environment.
Still no match for Go though, shipping a single cross-compiled binary is a joy. And with a bit of trickery you can even bundle in your whole static website in it :) Works great when you're building business logic with a simple UI on top.
porridgeraisin · 5m ago
> std-lib
Yes, My favourite is the `time` package. It's just so elegant how it's just a number under there, the nominal type system truly shines. And using it is a treat.
What do you mean I can do `+= 8*time.Hour` :D
the_duke · 29m ago
I personally don't like Go, and it has many shortcomings, but there is a reason it is popular regardless:
Go is a reasonably performant language that makes it pretty straightforward to write reliable, highly concurrent services that don't rely on heavy multithreading - all thanks to the goroutine model.
There really was no other reasonably popular, static, compiled language around when Google came out.
And there still barely is - the only real competitor that sits in a similar space is Java with the new virtual threads.
Languages with async/await promise something similar, but in practice are burdened with a lot of complexity (avoiding blocking in async tasks, function colouring, ...)
I'm not counting Erlang here, because it is a very different type of language...
So I'd say Go is popular despite the myriad of shortcomings, thanks to goroutines and the Google project street cred.
cogman10 · 13m ago
Slowly but surely, the jvm has been closing the go gap. With efforts like virtual threads, zgc, lilliput, Leyden, and Valhalla, the jvm has been closing the gap.
The change from Java 8 to 25 is night and day. And the future looks bright. Java is slowly bringing in more language features that make it quite ergonomic to work with.
theshrike79 · 8m ago
I'm still traumatised by Java from my earlier career. So many weird patterns, FactoryFactories and Spring Framework and ORMs that work 90% of the time and the 10% is pure pain.
I have no desire to go back to Java no matter how much the language has evolved.
For me C# has filled the void of Java in enterprise/gaming environments.
theshrike79 · 6m ago
The comparative strictness and simplicity of Go also makes it a good option for LLM-assisted programming.
Every single piece of Go 1.x code scraped from the internet and baked in to the models is still perfectly valid and compiles with the latest version.
gf000 · 20m ago
> And there still barely is - the only real competitor that sits in a similar space is Java with the new virtual threads
Which Google uses far more commonly than Go, still to this day.
fabian2k · 20m ago
There are real pain points with async/await, but I find the criticism there often overblown. Most of the issues go away if you go pure async, mixing older sync code with async is much more difficult though.
My experience is mostly with C#, but async/await works very well there in my experience. You do need to know some basics there to avoid problem, but that's the case for essentially every kind of concurrency. They all have footguns.
zwnow · 24m ago
What modern language is a better fit for new projects in your opinion?
gf000 · 16m ago
For web frontend: js
For ML/data: python
For backend/general purpose software: Java
The only silver bullet we know of is building on existing libraries. These are also non-accidentally the top 3 most popular languages according to any ranking worthy of consideration.
tedk-42 · 12m ago
I'd swap java with go any day of the week. I never liked how much 'code-padding' is required with java `public static void main`
kasperni · 5m ago
For Java 25 which is planned to be released in a couple of weeks:
First, we allow main methods to omit the infamous boilerplate of public static void main(String[] args), which simplifies the Hello, World! program to:
class HelloWorld {
void main() {
System.out.println("Hello, World!");
}
}
Second, we introduce a compact form of source file that lets developers get straight to the code, without a superfluous class declaration:
Third, we add a new class in the java.lang package that provides basic line-oriented I/O methods for beginners, thereby replacing the mysterious System.out.println with a simpler form:
void main() {
IO.println("Hello, World!");
}
gf000 · 5m ago
It's rich to complain about verbosity coming from Go.
Nonetheless, Java has eased the psvm requirements, you don't even have to explicitly declare a class and a void main method is enough. [1] Not that it would matter for any non-script code.
Java, lol. Enterprise lang with too many abstractions and wrongly interpreted OOP. Absolutely not.
aloukissas · 22m ago
Elixir, with types
pmarreck · 1m ago
I love Elixir but you cannot compile it into a single binary, it is massively concurrent but single-threaded slow, and deployment is still nontrivial.
That said, pretty much everything else about it is amazing though IMHO and it has unique features you won’t find almost anywhere else
sarchertech · 8m ago
That doesn’t exist yet. Also Elixir is in no way a replacement for Go.
It can’t match it for performance. There’s no mutable array, almost everything is a linked list, and message passing is the only way to share data.
I primarily use Elixir in my day job, but I just had to write high performance tool for data migration and I used Go for that.
zwnow · 8m ago
This one i can get behind.
positron26 · 9m ago
Count Rust. From what I can see, it's becoming very popular in the microservices landscape. Not hard to imagine why. Multithreading is a breeze. Memory use is low. Latency is great.
fschuett · 21m ago
Technically, the term "billion dollar mistake", coined in 1965, would now be a "10 billion dollar mistake" in 2025. Or, if the cost is measured in terms of housing, it would be a "21 billion dollar mistake".
:^/
jact · 34m ago
I worked briefly on extending an Go static site generator someone wrote for a client. The code was very clear and easy to read, but difficult to extend due to the many rough edges with the language. Simple changes required altering a lot of code in ways that were not immediately obvious. The ability to encapsulate and abstract is hindered in the name of “simplicity.” Abstraction is the primary way we achieve simple and easy to extend code. John Ousterhoust defined a complex program as one that is difficult to extend rather than necessarily being large or difficult to understand at scale. The average Go program seems to violate this principle a lot. Programs appear “simple” but extension proves difficult and fraught.
Go is a case of the emperor having no clothes. Telling people that they just don’t get it or that it’s a different way of doing things just doesn’t convince me. The only thing it has going for it is a simple dev experience.
torginus · 38m ago
I still don't understand why defer works on function scope, and not lexical scope, and nobody has been able to explain to me the reason for it.
In fact this was so surprising to me is that I only found out about it when I wrote code that processed files in a loop, and it started crashing once the list of files got too big, because defer didnt close the handles until the function returned.
When I asked some other Go programmers, they told me to wrap the loop body in an anonymus func and invoke that.
gwd · 28m ago
So sometimes you want it lexical scope, and sometimes function scope; For example, maybe you open a bunch of files in a loop and need them all open for the rest of the function.
Right now it's function scope; if you need it lexical scope, you can wrap it in a function.
Suppose it were lexical scope and you needed it function scope. Then what do you do?
masklinn · 4m ago
> Suppose it were lexical scope and you needed it function scope. Then what do you do?
Defer a bulk thing at the function scope level, and append files to an array after opening them.
gf000 · 13m ago
Making it lexical scope would make both of these solvable, and would be clear for anyone reading it.
You can just introduce a new scope wherever you want with {} in sane languages, to control the required behavior as you wish.
grey-area · 37m ago
There’s probably no deep reason, does it matter much?
christophilus · 31m ago
I’ve worked with languages that have both, and find myself wishing I could have function-level defer inside conditionals when I use the block-level languages.
cabirum · 10m ago
Lexical scope does not have a stack to put defer onto.
masklinn · 1m ago
All the defer sites in a lexical scope are static, you can target those sites directly or add a fixed-size stack in the frame.
andy_ppp · 20m ago
They are forcing people to write Typescript code like it’s Golang where I am right now (amongst other extremely stupid decisions - only unit test service boundaries, do not pull out logic into pure functions, do not write UI tests, etc.). I really must remember to ask organisations to show me their code before joining them.
theshrike79 · 5m ago
Have you seen Java people write Python? Same vibe :)
pjmlp · 2m ago
As usual, lets revisit something that Pascal could do in 1976,
type
StatusCodes = (Success, Ongoing, Done)
Go in 2025,
type StatusCodes int
const (
Success StatusCodes = iota
Ongoing
Done
)
thiht · 2m ago
Where's Pascal today?
tex0 · 40m ago
If you don't like Go, then just let go. I hope nobody forces you to use it.
Some critique is definitely valid, but some of it just sounds like they didn't take the time to grasp the language. It's trade offs all the way. For example there is a lot I like about Rust, but still no my favorite language.
klabb3 · 26m ago
Disagree. Most critiques of Go I've read have been weak. This one was decent. And I say that as a big enjoyer of Go.
That said I really wish there was a revamp where they did things right in terms of nil, scoping rules etc. However, they've commited to never breaking existing programs (honorable, understandable) so the design space is extremely limited. I prefer dealing with local awkwardness and even excessive verbosity over systemic issues any day.
ben0x539 · 26m ago
Few things are truly forced upon me in life but walking away from everything that I don't like would be foolish. There is compromise everywhere and I don't think entering into a tradeoff means I'm not entitled to have opinions about the things I'm trading off.
I don't think the article sounds like someone didn't take the time to grasp the language. It sounds like it's talking about the kind of thing that really only grates on you after you've seriously used the language for a while.
ddlsmurf · 7m ago
Sure but life choices are one thing, but this critique is still valuable. I learned a thing or two, and also think go can improve (I understand it's because I don't grok the language but I still prefer map to append in a loop)
7thpower · 32m ago
Which begs the question: What is your favorite language?
I don't really care if you want that. Everyone should know that that's just the way slices work. Nothing more nothing less.
I really don't give a damn about that, i just know how slices behave, because I learned the language. That's what you should do when you are programming with it (professionally)
lvl155 · 9m ago
I think a lot of people got on the Go train because of Google and not necessarily because it was good. There was a big adoption in Chinese tech scene for example. I personally think Rust/Go/Zig and other modern languages suffer a bit from trying too hard not to be C/C++/Java.
jonathan920 · 26m ago
Oh no , Rust is too tough, go is no good, am i going back to java?
maxloh · 15m ago
Maybe the new in-development Carbon language? It sounds promising, but it is nowhere near its 1.0 release.
figmert · 50m ago
Has Go become the new PHP? Every now and then I see an article complaining about Go's shortcomings.
giancarlostoro · 46m ago
No, this has been the case as long as Go has been around, then you look and its some C or C++ developer with specific needs, thats okay, its not for everyone.
jact · 22m ago
I think with C or C++ devs, those who live in glass houses shouldn’t throw stones.
I would criticize Go from the point of view of more modern languages that have powerful type systems like the ML family, Erlang/Elixir or even the up and coming Gleam. These languages succeed in providing powerful primitives and models for creating good, encapsulating abstractions. ML languages can help one entirely avoid certain errors and understand exactly where a change to code affects other parts of the code — while languages like Erlang provided interesting patterns for handling runtime errors without extensive boilerplate like Go.
It’s a language that hobbles developers under the aegis of “simplicity.” Certainly, there are languages like Python which give too much freedom — and those that are too complex like Rust IMO, but Go is at best a step sideways from such languages. If people have fun or get mileage out of it, that’s fine, but we cannot pretend that it’s really this great tool.
gf000 · 11m ago
> I would criticize Go from the point of view of more modern languages that have powerful type systems like the ML
Go release date: 2012
ML: 1997
ginko · 43m ago
Go was announced as a replacement for C & C++ so I think it's reasonable to compare it to that.
Matl · 31m ago
It was intended as a as a replacement for C & C++ for Google's use case of network services btw.
wild_egg · 28m ago
It hasn't been promoted that way for over a decade at this point.
raincole · 19m ago
It means many people are using it. That's it.
Xelbair · 16m ago
Go was always 80% there,but the last missing(hard) 20% wasn't ever done.
It is infuriating because it is close to being good, but it will never get there - now due to backwards compatibility.
Also Rob Pike quote about Go's origins is spot on.
pydry · 41m ago
Go is a pretty good example of how mediocre technology that would never have taken off on its own merits benefits from the rose tinted spectacles that get applied when FAANG starts a project.
christophilus · 28m ago
I don’t buy this at all. I picked up Go because it has fast compilation speed, produces static binaries, can build useful things without a ton of dependencies, is relatively easy to maintain, and has good tooling baked in. I think this is why it gained adoption vs Dart or whatever other corporate-backed languages I’m forgetting.
theshrike79 · 3m ago
[delayed]
pydry · 22m ago
I tried out one project because of these attributes and then scrapped it fairly quickly in favor of rust. Not enough type safety, too much verbosity. Too much fucking "if err != nil".
The language sits in an awkward space between rust and python where one of them would almost always be a better choice.
But, google rose colored specs...
throwawayxcmz · 19m ago
Exactly.
The other jarring example of this kind of deferring logical thinking to big corps was people defending Apple's soldering of memory and ssd, specially so on this site, until some Chinese lad proved that all the imagined issues for why Apple had to do such and such was bs post hoc rationalisation.
The same goes with Go, but if you spend enough time, every little while you see the disillusionment of some hardcore fans, even from the Go's core team, and they start asking questions but always start with things like "I know this is Go and holy reasons exists and I am doing a sin to question but why X or Y". It is comedy.
softwaredoug · 43m ago
I like Go, but my main annoyance is deciding when to use a pointer or not use a pointer as variable/receiver/argument. And if its an interface variable, it has a pointer to the concrete instance in the interface 'struct'. Some things are canonically passed as pointers like contexts.
It just feels sloppy and I'm worried I'm going to make a mistake.
vbezhenar · 39m ago
Just use pointers everywhere? Who cares.
grey-area · 39m ago
I just always use pointers for structs.
nikolayasdf123 · 26m ago
I 80% of time use structs. common misunderstanding: it does not reduce performance for pointer vs value receivers (Go compiler generates same code for both, no copy of struct receiver happens). most of structs are small anyways, safe to copy. Go also automatically translates value receivers and pointer receivers back-and-forth. and if I see pointer I see something that can be mutated (or very large). in fact, if I see a pointer, I think "here we go.. will it be mutated?". written 400,000 LOC in Go, rarely seeing this issue.
ochronus · 1m ago
s/good/perfect
sublimefire · 24m ago
This post is just an attention grabbing rage bate. Listed issues are superficial unless the person is a bit far into the spectrum. There is no good datapoint which would weigh the issues against real world problems, i.e. how much does it cost. Even the point about ram is weak without the data.
pif · 46m ago
It doesn't need to be good because it is not meant for good developers.
Buttons840 · 28m ago
And it's perfect for most business software, because most businesses are not focused on building good software.
Go has a good-enough standard library, and Go can support a "pile-of-if-statements" architecture. This is all you need.
Most enterprise environments are not handled with enough care to move beyond "pile-of-if-statements". Sure, maybe when the code was new it had a decent architecture, but soon the original developers left and then the next wave came in and they had different ideas and dreamed of a "rewrite", which they sneakily started but never finished, then they left, and the 3rd wave of developers came in and by that point the code was a mess and so now they just throw if-statements onto the pile until the Jira tickets are closed, and the company chugs along with its shitty software, and if the company ever leaks the personal data of 100 million people, they aren't financially liable.
theshrike79 · 2m ago
[delayed]
nikolayasdf123 · 47m ago
if this is the worst, not too bad.
giancarlostoro · 46m ago
Agree, most of us arent needing niche C++ / C language features, what Go has for us is sufficient.
asmor · 30m ago
Skill issue, and also wash your mouth.
1. If you want bounded scope, use an inline function. Works for defer too.
2. Array manipulation depending on memory space is a bit of a footgun, but I'd argue you usually don't manipulate a copy and then keep the source around. You usually assign the first argument of append back to itself. There's copy for the rare case you don't. The alternative is to have more indirect pointers, and you hate those too!
3. I have literally never had the issue that library code uses panic. Also they're not exceptions. They're bluescreen-level bugchecks where you "press enter to continue" at your own risk. It's usually fine and most HTTP libraries wrap requests in a recover for you, but it's not flow control.
4. If you don't know what's safe to do with a file handle you can thank libc for that, not Go.
guappa · 21m ago
I've had library code cause a segmentation fault. I think that is even worse.
bhickey · 10m ago
I've had Go's garbage collector free memory that it never allocated in the first place.
zwnow · 26m ago
> Wait, what? Why is err reused for foo2()? Is there’s something subtle I’m not seeing? Even if we change that to :=, we’re left to wonder why err is in scope for (potentially) the rest of the function. Why? Is it read later?
First time its assigned nil, second time its overwritten in case there's an error in the 2nd function. I dont see the authors issue? Its very explicit.
gwd · 24m ago
Anyone want to try to explain what he's on about with the first example?
bar, err := foo()
if err != nil {
return err
}
if err := foo2(); err != nil {
return err
}
The above (which declares a new value of err scoped to the second if statement) should compile right? What is it that he's complaining about?
EDIT: OK, I think I understand; there's no easy way to have `bar` be function-scoped and `err` be if-scoped.
I mean, I'm with him on the interfaces. But the "append" thing just seems like ranting to me. In his example, `a` is a local variable; why would assigning a local variable be expected to change the value in the caller? Would you expect the following to work?
int func(a *MyStruct) {
a = &MyStruct{...}
}
If not why would you expect `a = apppend(a, ...)` to work?
mrweasel · 17m ago
That might be it, but I wondered about that one, as well as the append complaint. It seems like the author disagree with scoping rules, but they aren't really any different than a lot of other languages.
If someone really doesn't like the reuse of err, there's no reason why they couldn't create separate variable, e.g. err_foo and err_foo2. There's not no reason to not reuse err.
terminalbraid · 19m ago
You didn't copy the code correctly from the first example.
gwd · 11m ago
Well no, the second "if" statement is a red herring. Both of the following work:
bar, err := foo()
if err != nil {
return err
}
if err = foo2(); err != nil {
return err
}
and
bar, err := foo()
if err != nil {
return err
}
if err := foo2(); err != nil {
return err
}
He even says as much:
> Even if we change that to :=, we’re left to wonder why err is in scope for (potentially) the rest of the function. Why? Is it read later?
My initial reaction was: "The first `err` is function-scope because the programmer made it function-scope; he clearly knows you can make them local to the if, so what's he on about?`
It was only when I tried to rewrite the code to make the first `err` if-scope that I realized the problem I guess he has: OK, how do you make both `err` variable if-scope while making `bar` function-scope? You'd have to do something like this:
var bar MyType
if lbar, err := foo(); err != nil {
return err
} else {
bar = lbar
}
Which is a lot of cruft to add just to restrict the scope of `err`.
sublimefire · 18m ago
edit: the main rant about err was that it is left in scope but I believe the author does not like that
commandersaki · 15m ago
“What color is your nil?” — The two billion dollar mistake.
Talk about hyperbole.
crinkly · 26m ago
I dislike Go but I haven’t found anything else I dislike less.
antiquark · 26m ago
I'm still appalled that there's no "do while" loop in go.
pansa2 · 17m ago
Python doesn’t have one either
YetAnotherNick · 20m ago
What does this mean? Do they just use recover and keep bad data?
> The standard library does that. fmt.Print when calling .String(), and the standard library HTTP server does that, for exceptions in the HTTP handlers.
Apart from this most doesn't seem that big of a deal, except for `append` which is truly a bad syntax. If you doing it inplace append don't return the value.
baq · 42m ago
> Though Python is almost entirely refcounted, so one can pretty much rely on the __del__ finalizer being called.
yeah no. you need an acyclic structure to maybe guarantee this, in CPython. other Python implementations are more normal in that you shouldn't rely on finalizers at all.
sgarland · 33m ago
I love Python, but the sheer number of caveats and warnings for __del__ makes me question if this person has ever read the docs [0]. My favorite WTF:
> It is possible (though not recommended!) for the __del__() method to postpone destruction of the instance by creating a new reference to it. This is called object resurrection.
How does this relate to the claim of the parent comment that cyclic structures are never freed in python (which is false, btw)?
sgarland · 13m ago
When I replied, the only thing the comment said was “yeah no.” I was agreeing that __del__ is fraught with peril.
Reading: cyclic GC, yes, the section I linked explicitly discusses that problem, and how it’s solved.
porridgeraisin · 37m ago
> Previous posts Why Go is not my favourite language and Go programs are not portable have me critiquing Go for over a decade.
I chuckled
akoboldfrying · 31m ago
defer is no worse than Java's try-with-resources. Neither is true RAII, because in both cases you, the caller, need to remember to write the wordy form ("try (...) {" or "defer ...") instead of the plain form ("..."), which will still compile but silently do the wrong thing.
xyzzyz · 11m ago
Sure, true RAII would be improvement over both, but the author's point is that Java is an improvement over Go, because the resource acquisition is lexical scoped, not function-scoped. Imagine if Java's `try (...) { }` didn't clear the resource when the try block ends, but rather when the wrapping method returns. That's how Go's defer works.
akoboldfrying · 7m ago
Can't you create a new block scope in Go? If not, I agree. If so, just do that if you want lexical scoping?
keyle · 2h ago
I use Go daily for work, alongside Dart, Python.
I say switching to Go is like a different kind of Zen. It takes time, to settle in and get in the flow of Go... Unlike the others, the LSP is fast, the developer, not so much. Once you've lost all will to live you become quite proficient at it. /s
theshrike79 · 38s ago
[delayed]
aloukissas · 17m ago
I also sing "Fade to Black" when I have to write go :D
written-beyond · 45m ago
My developer experience was similar to rust but more frustrating because of the lax typing.
ISTG if I get downvoted for sharing my opinion I will give up on life.
slackfan · 25m ago
Still better (compiler speed) than Rust.
gf000 · 8m ago
Still not playing remotely in the same league. Only one of them is a "systems language", reusing Go's inappropriate marketing term.
But I can't help but agree with a lot of points in this article. Go was designed by some old-school folks that maybe stuck a bit too hard to their principles, losing sight of the practical conveniences. That said, it's a _feeling_ I have, and maybe Go would be much worse if it had solved all these quirks. To be fair, I see more leniency in fixing quirks in the last few years, like at some point I didn't think we'd ever see generics, or custom iterators, etc.
The points about RAM and portability seem mostly like personal grievances though. If it was better, that would be nice, of course. But the GC in Go is very unlikely to cause issues in most programs even at very large scale, and it's not that hard to debug. And Go runs on most platforms anyone could ever wish to ship their software on.
But yeah the whole error / nil situation still bothers me. I find myself wishing for Result[Ok, Err] and Optional[T] quite often.
I'd say that it's entirely the other way around: they stuck to the practical convenience of solving the problem that they had in front of them, quickly, instead of analyzing the problem from the first principles, and solving the problem correctly (or using a solution that was Not Invented Here).
Go's filesystem API is the perfect example. You need to open files? Great, we'll create
function, you can open files now, done. What if the file name is not valid UTF-8, though? Who cares, hasn't happen to me in the first 5 years I used Go.Nothing? Neither Go nor the OS require file names to be UTF-8, I believe
The issue is that it was a bit outdated in the choice of _which_ things to choose as the one Go way. People expect a map/filter method rather than a loop with off by one risks, a type system with the smartness of typescript (if less featured and more heavily enforced), error handling is annoying, and so on.
I get that it’s tough to implement some of those features without opening the way to a lot of “creativity” in the bad sense. But I feel like go is sometimes a hard sell for this reason, for young devs whose mother language is JavaScript and not C.
In what universe?
Is it the best or most robust or can you do fancy shit with it? No
But it works well enough to release reliable software along with the massive linter framework that's built on top of Go.
The code was on the hot path of their central routing server handling Billions (with a B) messages in a second or something crazy like that.
You're not building Discord, the GC will most likely never be even a blip in your metrics. The GC is just fine.
I agree.
The Go std-lib is fantastic.
Also no dependency-hell with Go, unlike with Python. Just ship an oven-ready binary.
And what's the alternative ?
Java ? Licensing sagas requiring the use of divergent forks. Plus Go is easier to work with, perhaps especially for server-side deployments.
Zig ? Rust ? Complex learning curve. And having to choose e.g. Rust crates re-introduces dependency hell and the potential for supply-chain attacks.
you can go `uv run script.py` and it'll automatically fetch the libraries and run the script in a virtual environment.
Still no match for Go though, shipping a single cross-compiled binary is a joy. And with a bit of trickery you can even bundle in your whole static website in it :) Works great when you're building business logic with a simple UI on top.
Yes, My favourite is the `time` package. It's just so elegant how it's just a number under there, the nominal type system truly shines. And using it is a treat. What do you mean I can do `+= 8*time.Hour` :D
Go is a reasonably performant language that makes it pretty straightforward to write reliable, highly concurrent services that don't rely on heavy multithreading - all thanks to the goroutine model.
There really was no other reasonably popular, static, compiled language around when Google came out.
And there still barely is - the only real competitor that sits in a similar space is Java with the new virtual threads.
Languages with async/await promise something similar, but in practice are burdened with a lot of complexity (avoiding blocking in async tasks, function colouring, ...)
I'm not counting Erlang here, because it is a very different type of language...
So I'd say Go is popular despite the myriad of shortcomings, thanks to goroutines and the Google project street cred.
The change from Java 8 to 25 is night and day. And the future looks bright. Java is slowly bringing in more language features that make it quite ergonomic to work with.
I have no desire to go back to Java no matter how much the language has evolved.
For me C# has filled the void of Java in enterprise/gaming environments.
Every single piece of Go 1.x code scraped from the internet and baked in to the models is still perfectly valid and compiles with the latest version.
Which Google uses far more commonly than Go, still to this day.
My experience is mostly with C#, but async/await works very well there in my experience. You do need to know some basics there to avoid problem, but that's the case for essentially every kind of concurrency. They all have footguns.
For ML/data: python
For backend/general purpose software: Java
The only silver bullet we know of is building on existing libraries. These are also non-accidentally the top 3 most popular languages according to any ranking worthy of consideration.
----- https://openjdk.org/jeps/512 -----
First, we allow main methods to omit the infamous boilerplate of public static void main(String[] args), which simplifies the Hello, World! program to:
Second, we introduce a compact form of source file that lets developers get straight to the code, without a superfluous class declaration: Third, we add a new class in the java.lang package that provides basic line-oriented I/O methods for beginners, thereby replacing the mysterious System.out.println with a simpler form:Nonetheless, Java has eased the psvm requirements, you don't even have to explicitly declare a class and a void main method is enough. [1] Not that it would matter for any non-script code.
[1] https://openjdk.org/jeps/495
That said, pretty much everything else about it is amazing though IMHO and it has unique features you won’t find almost anywhere else
It can’t match it for performance. There’s no mutable array, almost everything is a linked list, and message passing is the only way to share data.
I primarily use Elixir in my day job, but I just had to write high performance tool for data migration and I used Go for that.
:^/
Go is a case of the emperor having no clothes. Telling people that they just don’t get it or that it’s a different way of doing things just doesn’t convince me. The only thing it has going for it is a simple dev experience.
In fact this was so surprising to me is that I only found out about it when I wrote code that processed files in a loop, and it started crashing once the list of files got too big, because defer didnt close the handles until the function returned.
When I asked some other Go programmers, they told me to wrap the loop body in an anonymus func and invoke that.
Right now it's function scope; if you need it lexical scope, you can wrap it in a function.
Suppose it were lexical scope and you needed it function scope. Then what do you do?
Defer a bulk thing at the function scope level, and append files to an array after opening them.
You can just introduce a new scope wherever you want with {} in sane languages, to control the required behavior as you wish.
Some critique is definitely valid, but some of it just sounds like they didn't take the time to grasp the language. It's trade offs all the way. For example there is a lot I like about Rust, but still no my favorite language.
That said I really wish there was a revamp where they did things right in terms of nil, scoping rules etc. However, they've commited to never breaking existing programs (honorable, understandable) so the design space is extremely limited. I prefer dealing with local awkwardness and even excessive verbosity over systemic issues any day.
I don't think the article sounds like someone didn't take the time to grasp the language. It sounds like it's talking about the kind of thing that really only grates on you after you've seriously used the language for a while.
I don't really care if you want that. Everyone should know that that's just the way slices work. Nothing more nothing less.
I really don't give a damn about that, i just know how slices behave, because I learned the language. That's what you should do when you are programming with it (professionally)
I would criticize Go from the point of view of more modern languages that have powerful type systems like the ML family, Erlang/Elixir or even the up and coming Gleam. These languages succeed in providing powerful primitives and models for creating good, encapsulating abstractions. ML languages can help one entirely avoid certain errors and understand exactly where a change to code affects other parts of the code — while languages like Erlang provided interesting patterns for handling runtime errors without extensive boilerplate like Go.
It’s a language that hobbles developers under the aegis of “simplicity.” Certainly, there are languages like Python which give too much freedom — and those that are too complex like Rust IMO, but Go is at best a step sideways from such languages. If people have fun or get mileage out of it, that’s fine, but we cannot pretend that it’s really this great tool.
Go release date: 2012
ML: 1997
It is infuriating because it is close to being good, but it will never get there - now due to backwards compatibility.
Also Rob Pike quote about Go's origins is spot on.
The language sits in an awkward space between rust and python where one of them would almost always be a better choice.
But, google rose colored specs...
The other jarring example of this kind of deferring logical thinking to big corps was people defending Apple's soldering of memory and ssd, specially so on this site, until some Chinese lad proved that all the imagined issues for why Apple had to do such and such was bs post hoc rationalisation.
The same goes with Go, but if you spend enough time, every little while you see the disillusionment of some hardcore fans, even from the Go's core team, and they start asking questions but always start with things like "I know this is Go and holy reasons exists and I am doing a sin to question but why X or Y". It is comedy.
It just feels sloppy and I'm worried I'm going to make a mistake.
Go has a good-enough standard library, and Go can support a "pile-of-if-statements" architecture. This is all you need.
Most enterprise environments are not handled with enough care to move beyond "pile-of-if-statements". Sure, maybe when the code was new it had a decent architecture, but soon the original developers left and then the next wave came in and they had different ideas and dreamed of a "rewrite", which they sneakily started but never finished, then they left, and the 3rd wave of developers came in and by that point the code was a mess and so now they just throw if-statements onto the pile until the Jira tickets are closed, and the company chugs along with its shitty software, and if the company ever leaks the personal data of 100 million people, they aren't financially liable.
1. If you want bounded scope, use an inline function. Works for defer too.
2. Array manipulation depending on memory space is a bit of a footgun, but I'd argue you usually don't manipulate a copy and then keep the source around. You usually assign the first argument of append back to itself. There's copy for the rare case you don't. The alternative is to have more indirect pointers, and you hate those too!
3. I have literally never had the issue that library code uses panic. Also they're not exceptions. They're bluescreen-level bugchecks where you "press enter to continue" at your own risk. It's usually fine and most HTTP libraries wrap requests in a recover for you, but it's not flow control.
4. If you don't know what's safe to do with a file handle you can thank libc for that, not Go.
First time its assigned nil, second time its overwritten in case there's an error in the 2nd function. I dont see the authors issue? Its very explicit.
EDIT: OK, I think I understand; there's no easy way to have `bar` be function-scoped and `err` be if-scoped.
I mean, I'm with him on the interfaces. But the "append" thing just seems like ranting to me. In his example, `a` is a local variable; why would assigning a local variable be expected to change the value in the caller? Would you expect the following to work?
If not why would you expect `a = apppend(a, ...)` to work?If someone really doesn't like the reuse of err, there's no reason why they couldn't create separate variable, e.g. err_foo and err_foo2. There's not no reason to not reuse err.
> Even if we change that to :=, we’re left to wonder why err is in scope for (potentially) the rest of the function. Why? Is it read later?
My initial reaction was: "The first `err` is function-scope because the programmer made it function-scope; he clearly knows you can make them local to the if, so what's he on about?`
It was only when I tried to rewrite the code to make the first `err` if-scope that I realized the problem I guess he has: OK, how do you make both `err` variable if-scope while making `bar` function-scope? You'd have to do something like this:
Which is a lot of cruft to add just to restrict the scope of `err`.Talk about hyperbole.
> The standard library does that. fmt.Print when calling .String(), and the standard library HTTP server does that, for exceptions in the HTTP handlers.
Apart from this most doesn't seem that big of a deal, except for `append` which is truly a bad syntax. If you doing it inplace append don't return the value.
yeah no. you need an acyclic structure to maybe guarantee this, in CPython. other Python implementations are more normal in that you shouldn't rely on finalizers at all.
> It is possible (though not recommended!) for the __del__() method to postpone destruction of the instance by creating a new reference to it. This is called object resurrection.
[0]: https://docs.python.org/3/reference/datamodel.html#object.__...
Reading: cyclic GC, yes, the section I linked explicitly discusses that problem, and how it’s solved.
I chuckled
I say switching to Go is like a different kind of Zen. It takes time, to settle in and get in the flow of Go... Unlike the others, the LSP is fast, the developer, not so much. Once you've lost all will to live you become quite proficient at it. /s
ISTG if I get downvoted for sharing my opinion I will give up on life.