vit*_*itr 6 concurrency timeout channel idiomatic go
我需要从Go通道读取数据一段时间(比如说5秒).带超时的select语句对我来说不起作用,因为我需要读取尽可能多的值并在5秒后完全停止.到目前为止,我已经提出了一个使用额外时间通道的解决方案https://play.golang.org/p/yev9CcvzRIL
package main
import "time"
import "fmt"
func main() {
// I have no control over dataChan
dataChan := make(chan string)
// this is a stub to demonstrate some data coming from dataChan
go func() {
for {
dataChan <- "some data"
time.Sleep(time.Second)
}
}()
// the following is the code I'm asking about
timeChan := time.NewTimer(time.Second * 5).C
for {
select {
case d := <-dataChan:
fmt.Println("Got:", d)
case <-timeChan:
fmt.Println("Time's up!")
return
}
}
}
Run Code Online (Sandbox Code Playgroud)
我想知道有没有更好或更有惯用的方法来解决这个问题?
icz*_*cza 12
这就是它.但如果您不需要停止或重置计时器,只需使用time.After()而不是time.NewTimer().time.After()是"等同于NewTimer(d).C" .
afterCh := time.After(5 * time.Second)
for {
select {
case d := <-dataChan:
fmt.Println("Got:", d)
case <-afterCh:
fmt.Println("Time's up!")
return
}
}
Run Code Online (Sandbox Code Playgroud)
或者(根据自己的喜好),您可以在声明中声明后通道,for如下所示:
for afterCh := time.After(5 * time.Second); ; {
select {
case d := <-dataChan:
fmt.Println("Got:", d)
case <-afterCh:
fmt.Println("Time's up!")
return
}
}
Run Code Online (Sandbox Code Playgroud)
另外我知道这只是一个例子,但总是认为你开始的goroutine将如何正确结束,因为在你的情况下生成数据的goroutine永远不会终止.
另外不要忘记,如果可以在不阻塞的情况下执行多个案例,则随机选择一个案例.因此,如果dataChan准备从"不间断"接收,则无法保证循环将在超时后立即终止.在实践中,这通常不是问题(从那开始即使超时也不是保证,看看Golang Timers的详细信息,长度为0),但你不应该忘记它在"任务 - 批评"应用程序中.有关详情,请参阅相关问题: