如何在命名管道中的 EOF 后恢复读取

car*_*ett 5 named-pipes go

我正在编写一个程序,该程序打开一个命名管道进行读取,然后处理写入该管道的任何行:

err = syscall.Mkfifo("/tmp/myfifo", 0666)
if err != nil {
    panic(err)
}

pipe, err := os.OpenFile("/tmp/myfifo", os.O_RDONLY, os.ModeNamedPipe)
if err != nil {
    panic(err)
}

reader := bufio.NewReader(pipe)
scanner := bufio.NewScanner(reader)

for scanner.Scan() {
    line := scanner.Text()
    process(line)
}
Run Code Online (Sandbox Code Playgroud)

只要写入过程不重新启动或由于其他原因发送 EOF,此操作就可以正常工作。当这种情况发生时,循环终止(正如 的规范所预期的那样Scanner)。

但是,我想保持管道打开以接受进一步的写入。当然,我可以重新初始化扫描仪,但我相信这会产生竞争条件,即当新进程开始写入管道时扫描仪可能尚未准备好。

还有其他选择吗?我需要直接使用类型吗File

小智 0

来自bufio GoDoc

当扫描停止时,Scan ... 返回 false,无论是到达输入末尾还是出现错误。

因此,您可以保持文件打开并读取直到 EOF,然后scanner.Scan()在文件更改时或定期触发(即创建一个 goroutine),并确保变量pipe不会超出范围,以便您可以引用它再次。

如果我正确理解您对竞争条件的担忧,这不会成为问题(除非写入和读取操作必须同步),但是当扫描仪重新初始化时,它最终会回到文件的开头。