go - 停止优雅阻塞的 goroutine
问题描述
我有一个不断阻止读取标准输入的 goroutine,如下所示:
func routine() {
for {
data := make([]byte, 8)
os.Stdin.Read(data);
otherChannel <-data
}
}
该例程等待通过标准输入读取 8 个字节并提供另一个通道。
我想从主线程优雅地停止这个 goroutine。但是,由于 goroutine 几乎总是会被阻止从标准输入读取,我找不到一个好的解决方案来强制它停止。我想到了类似的东西:
func routine(stopChannel chan struct{}) {
for {
select {
case <-stopChannel:
return
default:
data := make([]byte, 8)
os.Stdin.Read(data);
otherChannel <-data
}
}
}
但是,问题是如果stopChannel
关闭时 stdin 中没有更多输入,goroutine 将保持阻塞状态而不返回。
有没有一种好方法可以让它在主线程需要时立即返回?
谢谢。
解决方案
检测os.Stdin
是否已关闭:检查返回的错误值os.Stdin.Read()
。
额外的一点:尽管您声明在您的情况下您将始终收到 8 个字节的块,但您仍然应该检查您是否确实收到了 8 个字节的数据。
func routine() {
for {
data := make([]byte, 8)
n, err := os.Stdin.Read(data)
// error handling : the basic thing to do is "on error, return"
if err != nil {
// if os.Stdin got closed, .Read() will return 'io.EOF'
if err == io.EOF {
log.Printf("stdin closed, exiting")
} else {
log.Printf("stdin: %s", err)
}
return
}
// check that 'n' is big enough :
if n != 8 {
log.Printf("short read: only %d byte. exiting", n)
return // instead of returning, you may want to keep '.Read()'ing
// or you may use 'io.ReadFull(os.Stdin, data)' instead of '.Read()'
}
// a habit to have : truncate your read buffers to 'n' after a .Read()
otherChannel <-data[:n]
}
}
推荐阅读
- php - IF 条件在刀片模板中的 @auth 下不起作用
- typescript - Loopback post 请求无法过滤和排列
- javascript - Firebase 身份验证自定义声明导致加载程序出现问题
- angular - 为什么 ngSwitch 会无限渲染模板?
- jquery - 比较课程并采取行动/Comparer 2 classes et faire une action
- wordpress - 将图像从 Azure blob 存储上传到 Wordpress
- python - python ipywidgets 在 widgets.Text 中以编程方式强制峰会
- sql - 根据 Oracle DB 版本运行 sql
- android - 从周数获取周开始和结束天
- python - `type.__instancecheck__` 是否实现了 `isinstance` 的默认行为?