是否可以通过关闭src来中断io.Copy?
Is it possible to interrupt io.Copy by closing src?
代码示例:
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
中断它等待任何输入并仅在向标准输入发送内容后停止(例如只需按 enter)。
我希望关闭 Stdin 就像发送 EOF 一样,但它不起作用。
关闭 os.Stdin
将导致 io.Copy
变为 return,并在下次读取时出现错误 file already closed
(在 CTRL-C
之后,尝试按 Enter
).
如 File.Close 文档中所述:
Close closes the File, rendering it unusable for I/O.
您不能通过关闭(或任何其他方式)从 os.Stdin
强制 EOF return。相反,您需要包装 os.Stdin
并实现您自己的 Read
有条件地 return s EOF
的方法,或者在循环中读取有限数量的字节。
您可以在此 golang-nuts 主题中看到更多讨论和可能的解决方法。
您可以中断 io.Copy
而无需 关闭源端 - 通过传递已用可取消 context.Context
概述 here.
像这样修改上面的 goroutine:
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
或从上面的博客 link 中内嵌片段:
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}
}
代码示例:
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
中断它等待任何输入并仅在向标准输入发送内容后停止(例如只需按 enter)。
我希望关闭 Stdin 就像发送 EOF 一样,但它不起作用。
关闭 os.Stdin
将导致 io.Copy
变为 return,并在下次读取时出现错误 file already closed
(在 CTRL-C
之后,尝试按 Enter
).
如 File.Close 文档中所述:
Close closes the File, rendering it unusable for I/O.
您不能通过关闭(或任何其他方式)从 os.Stdin
强制 EOF return。相反,您需要包装 os.Stdin
并实现您自己的 Read
有条件地 return s EOF
的方法,或者在循环中读取有限数量的字节。
您可以在此 golang-nuts 主题中看到更多讨论和可能的解决方法。
您可以中断 io.Copy
而无需 关闭源端 - 通过传递已用可取消 context.Context
概述 here.
像这样修改上面的 goroutine:
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
或从上面的博客 link 中内嵌片段:
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}
}