The sample of code:
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()
}
If run this sample and try to interrupt by ^C
it waits for any input and stops only after sending something to stdin (e.g. just press enter).
I expect that closing Stdin will be like sending EOF, but it doesn't work.
Closing os.Stdin
will cause io.Copy
to return with error file already closed
next time it reads from it (after CTRL-C
, try pressing Enter
).
As explained in the File.Close docs:
Close closes the File, rendering it unusable for I/O.
You cannot force an EOF return from os.Stdin
by closing it (or any other way). Instead, you would need to either wrap os.Stdin
and implement your own Read
method that conditionally returns EOF
, or read a limited number of bytes in a loop.
You can see some more discussion and possible workarounds on this golang-nuts thread.