Priority of case versus default in golang select statements

Viewed 1992

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 cases 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.

1 Answers
Related