I am trying to set a file as input if a file name is given or use standard input if no file name is given. I would have thought that this is the way to do so:
var input io.Reader
if filename == "" {
input = os.Stdin
} else {
input, err = os.Open(filename)
if err != nil {
log.Fatalf("failed to open file: %v", err)
}
}
The function that is passed input
expects something that conforms to the io.Reader
interface and all behaves well. That is the above works ...
It works until I try to figure out a way to close input
. Although both things returned by os.Stdin and os.Open (sure, closing stdin might not really mean much, but it is harmless). The compiler doesn't know that both ways of creating input
give me something that implements Close(). So I was wondering there there is a way to tell the compiler that Close()
is implemented for input
.
CodePudding user response:
Use io.ReadCloser to declare that input
has Read and Close methods:
var input io.ReadCloser
if filename == "" {
input = os.Stdin
} else {
input, err = os.Open(filename)
if err != nil {
log.Fatalf("failed to open file: %v", err)
}
}
CodePudding user response:
The way to check if an io.Reader
implements Close
is to use type assertion as:
if closer, ok:=reader.(io.Closer); ok {
err:=closer.Close()
}
CodePudding user response:
Well in the course of writing up my question for others and working to spell things out, I realized that declaring input with
var input *os.File
fixes everything.
I have failed to look at the type of os.Stdin
until I started to write up the question. And so I declared input
in terms of the most general interface required by the function that will use it.