I have an application with multiple goroutines that are running for
loops, and need a way to signal these for
loops to break, and to test whether the timeout case occurred. I was looking into using a shared channel with select
statements to accomplish this as follows:
// elsewhere in the code, this channel is created, and passed below
done := make(chan struct{})
time.AfterFunc(timeout, func() { close(done) })
...
go func() {
Loop:
for {
select {
case <-done:
break Loop
default:
foo()
time.Sleep(1 * time.Second)
}
}
select {
case <-done:
panic("timed out!")
default:
// ok
}
}()
Is this a valid way to accomplish this? What I'm most concerned about is that the branch of a select
that is chosen could be non-deterministic, so that default
may be chosen even if one of the case
s is ready. Is this possible? Is there any documentation that states that a matching case
is guaranteed to have preference over a default
. The concern is that the for loop above could loop several times after done
is closed and/or report success even though a timeout occurred.