Earlier quoted context omitted.
Which is the case for Go: https://go.dev/ref/mem
A quote from your link: > programmers are strongly encouraged to use appropriate synchronization to avoid data races Any time you need to "encourage" programmers to do the right thing, you have already failed in your language design. And I think OP agrees with me here. OP says "static checking of correct synchronization" which is irresponsibly absent from Go.
The case of a leaky goroutine
41–50 of 87 posts
Re: The case of a leaky goroutine
#42I wish Go recorded the timestamp of goroutine and let you access them. An app I work on recently had a bug where goroutines would slowly build up over time. Turns out the bug is in the Growthbook SDK [1]. We can monitor the number of goroutines, but having a large number of goroutines waiting in the location that gets stuck is normal — we can only see such a problem over multiple days, in that the minimum value slowl…
Edit: Also, maybe the tool at this comment could've helped you? https://news.ycombinator.com/item?id=39817775
Re: The case of a leaky goroutine
#43Didn't Uber have some leaky goroutine detector? I vaguely remember seeing something like that, 5 years ago... Ah yeah it's here. https://github.com/uber-go/goleak
Uber also made something called fx, which is fantastic. You don't have to use it, but when you do, it helps ensure that you organize your code in a way that becomes very easily testable. It enforces a modular approach to composing together golang services. Being more easily testable helps prevent bugs, like these leaky goroutines.
I'm curious though, when do you reach for `fx` in a non-industrial project and when do you not? I still use the same patterns of separating out the implementation from the interface but I've been wiring in the dependencies by hand. I'm curious if folks reach for `fx` immediately or if it's something that requires thought to add. There's also Google's wire library [1] that does similar stuff but takes a compile time approach so it's a little easier to reason about if struct initialization screws up due to weird implicit things.
I still wire dependencies up by hand, but I'm curious what others do.
Re: The case of a leaky goroutine
#44I prefer multi threaded programming. Everything is off to the races (pun intended), you need to think long and hard about lifecycle management, who creates a resource, who will clean it up, how do you synchronize, where do you synchronize. It might be hard to get right sometimes. But the concept is simple. The tools you have available are simple. There's no "well everything works fine automagically unless it doesn't because these 10 lines of code".
Re: The case of a leaky goroutine
#45Earlier quoted context omitted.
Uber also made something called fx, which is fantastic. You don't have to use it, but when you do, it helps ensure that you organize your code in a way that becomes very easily testable. It enforces a modular approach to composing together golang services. Being more easily testable helps prevent bugs, like these leaky goroutines.
`fx` is mostly just Dependency Injection in Go which has been a thing in Java forever. I'm curious though, when do you reach for `fx` in a non-industrial project and when do you not? I still use the same patterns of separating out the implementation from the interface but I've been wiring in the dependencies by hand. I'm curious if folks reach for `fx` immediately or if it's something that requires thought to add. Th…
I realized quickly it wasn't absolutely necessary to use it since most people just make a package in golang, in order to get the separation they need. But when I started using it more and more, I noticed that taking advantage of the DI features of fx, also ensured that I wrote code that had clear separation of concerns.
In golang, it is too easy to just cross package include `new` things you need right in the function, instead of passing it in as an argument. This of course, makes it much harder to write tests for since you can't mock what you need easily.
The binary I built was distributed across tens of thousands of servers in multiple data centers, and had to run perfectly on every release as it took a lot of time/effort to even do updates. This meant comprehensive testing before deployment, so I wanted to optimize my unit/integration tests as much as possible.
I'm not sure it would be necessary for just simple api endpoint microservices, but for a complicated application binary that needs perfect testing, I can't imagine writing golang code without it. The benefits far outweigh the negatives.
Re: The case of a leaky goroutine
#46If Go allowed something like "handle = go foo()", goroutine could be automatically terminated when handle goes out of scope or becomes dead and is garbage collected. You can also use handle to cancel a goroutine etc. Go designers specifically avoided this model (of having a goroutine "id") for reasons I don't remember any more (may be to avoid making them heavier weight?) but this would be one way to stop leaky gorou…
Re: The case of a leaky goroutine
#47I'm gonna be that guy. The old man yelling at cloud. I don't get all this high level crap. Coroutines, goroutines, fibers, async/await. It's supposed to make concurrency easy and safe. But I just fail to build a working mental model for it. I get the rough idea, but every time there's an await I wonder where execution might jump next. And then you read stuff like this, how these super high level comfortable languages…
From the other comments here it’s not clear that there is a modern language that doesn’t have this problem.
Re: The case of a leaky goroutine
#48Earlier quoted context omitted.
`fx` is mostly just Dependency Injection in Go which has been a thing in Java forever. I'm curious though, when do you reach for `fx` in a non-industrial project and when do you not? I still use the same patterns of separating out the implementation from the interface but I've been wiring in the dependencies by hand. I'm curious if folks reach for `fx` immediately or if it's something that requires thought to add. Th…
I co-founded Java @ Apache, so my background is Java and DI was the first thing I was looking for when I started down the golang path. I tried out a bunch of different DI options for golang and settled on fx. fx is actually more than just DI, it is a whole framework for starting and stopping "services" as well. I realized quickly it wasn't absolutely necessary to use it since most people just make a package in golang…
Re: The case of a leaky goroutine
#49Thread leaks, which happen more frequently due to threaded async abstractions, such as the goroutine, are less often discussed than memory or CPU leaks, but are much more dangerous in multi-tenant container environments. A thread leak can lock up your entire node, including all the control plane processes. A container spec doesn't provide an easy way to control thread/nproc/ulimit limits (you can still do it, but it'…
Goroutines in a single process map onto a fixed number of threads. Even if you have goroutine leaks, you should not have thread leaks. Your program may deadlock or run out of memory, but it will not take the whole system down (at least, not in this way).
Not necessarilly true if you're using cgo
Re: The case of a leaky goroutine
#50To be fair, I do look forward to when logic programming languages get their time in The Sun.