如何在Go中以相同的方式对来自多个通道的输入做出反应?

I have some concurrent code that has two different timeout intervals, one static and one dynamic. I want to react the same way to both of them. This is the gist of it:

select {
case <-time.After(staticTimeoutInterval):
    doSomething()
case <-time.After(dynamicTimeoutInterval):
    doSomething()
}

Is there any way to write doSomething() only once? It's strange that select isn't as flexible as switch in this respect.

In your specific case you can use something like

timeout := min(staticTimeoutInterval, dynamicTimeoutInterval)

select {
case <-time.After(timeout):
    doSomething()
}

func min(a, b time.Duration) int {
    if a < b {
        return a
    }
    return b
}

About the seemingly inconsistent treatment of switch and select - while these statements have similar syntax, the purpose of switch is branched execution, while the purpose of select is communication.

If I can exaggerate:

  • switch is about the part after the case expression - the case expression here is mostly a simple, side-effect free expression
  • select is about the part in the case expression - the case expression here provides you with the important communication side effect and is not trivial to implement at all

Allowing fallthrough in select will allow you to save a couple of lines in some cases, but it will often make select statements harder to reason about. Given a similar choice in other situations, the Go creators have almost always gone with more verbose but simpler to understand.

What you got looks right. select cases do not fall through. And if it did, it would remove clarity and result in the same number of lines of code.