我正在尝试读取恒定的数据流,如果接收流的调用时间超过 30 秒,我需要超时并退出程序。我不知道如何在收到超时后退出 go 例程。
func ReceiveStreamMessages(strm Stream, msg chan<- []byte) error {
d := make(chan []byte, 1)
e := make(chan error)
tm := time.After(30 * time.Second)
go func() {
for {
//blocking call
data, err := strm.Recv()
if err != nil {
e <- err
return
}
select {
case d <- data.Result:
case <-tm:
//exit out go routine
return
}
}
}()
for {
select {
case message := <-d:
msg <- message
case err := <-e:
return err
case <-tm:
return nil
}
}
}
我上面的代码是错误的:为了让 select
在 go 例程的 for 循环中运行,阻塞函数必须返回并且数据将被填充,因此不会命中超时选择情况(或者随机执行,因为两者都已准备好)。退出父函数是否足以退出 go 例程?
最佳答案
使用context
包WithTimeout
。像这样的事情:
package main
import (
"context"
"fmt"
"sync"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
// prepare
...
// wait group just for test
var wg sync.WaitGroup
wg.Add(1)
go func() {
for {
select {
case d <- data.Result:
// do something
case <-ctx.Done():
fmt.Println("Done")
wg.Done()
return
}
}
}()
wg.Wait()
cancel()
fmt.Println("Hello, playground")
}
您可以在此处查看一个工作示例 https://play.golang.org/p/agi1fimtEkJ
关于Golang无限循环超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64008452/