是否可以中断io.通过关闭 src 复制?

  • 本文关键字:src 复制 中断 io 是否 go io
  • 更新时间 :
  • 英文 :


代码示例:

package main
import (
"io"
"os"
"os/signal"
"sync"
"syscall"
)
func main() {
sigintCh := make(chan os.Signal, 1)
signal.Notify(sigintCh, syscall.SIGINT, syscall.SIGTERM)
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
io.Copy(os.Stdout, os.Stdin)
}()
<-sigintCh
os.Stdin.Close()
wg.Wait()
}

如果运行此示例并尝试通过^C中断,它将等待任何输入,并且仅在向 stdin 发送内容后停止(例如,只需按回车键)。

我希望关闭 Stdin 就像发送 EOF 一样,但它不起作用。

关闭os.Stdin将导致io.Copy在下次读取时返回错误file already closed(CTRL-C后,请尝试按Enter)。

如 File.Close 文档中所述:

"关闭"关闭文件,使其不可用于 I/O。

您不能通过关闭 EOF(或任何其他方式)来强制从os.Stdin返回 EOF。相反,您需要包装os.Stdin并实现您自己的有条件返回EOFRead方法,或者在循环中读取有限数量的字节。

您可以在此 golang-nuts 线程上看到更多讨论和可能的解决方法。

您可以在关闭源端的情况下中断io.Copy- 通过传递已包装有逻辑的io.Reader,该逻辑采用此处概述的可取消context.Context

像这样修改你上面的程序:

ctx, cancel := context.WithCancel(context.Background())
go func() {
defer wg.Done()
r := NewReader(ctx, os.Stdin) // wrap io.Reader to make it context-aware
_, err := io.Copy(os.Stdout, r)
if err != nil {
// context.Canceled error if interrupted
}
}()
<-sigintCh
cancel() // canceling context will interrupt io.Copy operation

您可以从外部包(如 github.com/jbenet/go-context/io)导入NewReader,也可以从上面的博客链接中内联代码段:

type readerCtx struct {
ctx context.Context
r   io.Reader
}
func (r *readerCtx) Read(p []byte) (n int, err error) {
if err := r.ctx.Err(); err != nil {
return 0, err
}
return r.r.Read(p)
}
// NewReader gets a context-aware io.Reader.
func NewReader(ctx context.Context, r io.Reader) io.Reader {
return &readerCtx{ctx: ctx, r: r}
}

最新更新