Preventing goroutine leaks

Just a guy who loves to write code and watch anime.
Search for a command to run...

Just a guy who loves to write code and watch anime.
No comments yet. Be the first to comment.
Qualities that make outstanding builders.

Bipedal vs quadrupedal: how many legs This is about the number of legs the creature walks on. Bipedal. Two legs. Humans, ostriches, T-rex, kangaroos, most fantasy humanoids. Quadrupedal. Four legs. Do

Intro You hear "lerp" and "smoothstep" everywhere in game dev. They sound like math jargon. They're not. Both are small tools that do the same job: smoothly move from one value to another. The problem

What is Kinematics Kinematics is the math field. It's the study of how things move without worrying about forces (which would be dynamics). FK and IK are the two branches: forward kinematics and inver

Intro Textures are usually the biggest cost in a 3D scene. Memory, bandwidth, and load time all get eaten by them. Resizing them is the obvious lever. There's more. This post is about the less obvious

func doWork(done <-chan interface{}) <-chan interface{} {
terminated := make(chan interface{})
go func() {
defer close(terminated)
for {
select {
case s := <-strings:
// Do work
case <-done: // Parent says "stop working"
return
}
}
}()
return terminated
}
Key insight: Pass a done channel to every goroutine so the parent can signal cancellation.
newRandStream := func() <-chan int {
randStream := make(chan int)
go func() {
for {
randStream <- rand.Int() // runs forever!
}
}()
return randStream
}
newRandStream := func(done <-chan interface{}) <-chan int {
randStream := make(chan int)
go func() {
defer close(randStream)
for {
select {
case randStream <- rand.Int():
case <-done:
return // clean exit
}
}
}()
return randStream
}
This pattern shows up everywhere in Go:
for {
select {
case <-done:
return
default:
// do non-preemptable work
}
}
Two variations:
With default: Non-blocking, checks done channel between work
Without default: Blocking, waits for channels