I want to spawn a goroutine to listen to two channels of type chan int
and chan os.Signal
. I want the behavior to be specific depending on what's received on either channels. Meaning some os.Signal
may cause os.exit()
and some may not, some int
received through chan int
may print a statement and some may call a function, so I need this gorountine to be always running since the behaviors are different. And I'd like this to be all handed by one function.
I'm having a hard time figuring out how to achieve this syntactically. It doesn't seem like I can have range
loops inside of a select
block nor does it seem like I can have a select
block inside a range
loop. I can't find any resource online on this. Can someone give me an example?
You can put a select
statement in a for
loop (this is one of the examples in the language spec). Unlike a for...range
loop, this will let you read from both channels. It also won't automatically terminate if one of the channels closes. When you receive from a closed channel, a closed channel is always ready to receive and always produces a zero value, and there is a two-valued form of it that tells you whether the channel is open or not.
Your function might loosely look like
func HandleStuff(numbers <-chan int, signals <-chan os.Signal) {
var goingToExit bool
for {
select {
case n := <-numbers:
if n == 0 {
fmt.Printf("zero\n")
} else if n == 1 {
goingToExit = true
}
case sig, ok := <-signals:
if !ok { // the channel is closed
return
} else if goingToExit {
os.Exit(0)
}
}
}
}